mirror of
https://github.com/curl/curl.git
synced 2026-04-13 12:41:42 +08:00
TLS: add CURLOPT_SSL_SIGNATURE_ALGORITHMS and --sigalgs
Fixes #12982 Closes #16964
This commit is contained in:
parent
f9daa75a3b
commit
a638828c88
@ -122,7 +122,6 @@
|
||||
13.11 Some TLS options are not offered for HTTPS proxies
|
||||
13.13 Make sure we forbid TLS 1.3 post-handshake authentication
|
||||
13.14 Support the clienthello extension
|
||||
13.15 Select signature algorithms
|
||||
13.16 Share the CA cache
|
||||
13.17 Add missing features to TLS backends
|
||||
|
||||
@ -900,14 +899,6 @@
|
||||
https://datatracker.ietf.org/doc/html/rfc7685
|
||||
https://github.com/curl/curl/issues/2299
|
||||
|
||||
13.15 Select signature algorithms
|
||||
|
||||
Consider adding an option or a way for users to select TLS signature
|
||||
algorithm. The signature algorithms set by a client are used directly in the
|
||||
supported signature algorithm in the client hello message.
|
||||
|
||||
https://github.com/curl/curl/issues/12982
|
||||
|
||||
13.16 Share the CA cache
|
||||
|
||||
For TLS backends that supports CA caching, it makes sense to allow the share
|
||||
|
||||
@ -253,6 +253,7 @@ DPAGES = \
|
||||
show-error.md \
|
||||
show-headers.md \
|
||||
silent.md \
|
||||
sigalgs.md \
|
||||
skip-existing.md \
|
||||
socks4.md \
|
||||
socks4a.md \
|
||||
|
||||
33
docs/cmdline-opts/sigalgs.md
Normal file
33
docs/cmdline-opts/sigalgs.md
Normal file
@ -0,0 +1,33 @@
|
||||
---
|
||||
c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
SPDX-License-Identifier: curl
|
||||
Long: sigalgs
|
||||
Arg: <list>
|
||||
Help: TLS signature algorithms to use
|
||||
Protocols: TLS
|
||||
Added: 8.14.0
|
||||
Category: tls
|
||||
Multi: single
|
||||
See-also:
|
||||
- ciphers
|
||||
Example:
|
||||
- --sigalgs ecdsa_secp256r1_sha256 $URL
|
||||
---
|
||||
|
||||
# `--sigalgs`
|
||||
|
||||
Set specific signature algorithms to use during SSL session establishment according to RFC
|
||||
5246, 7.4.1.4.1.
|
||||
|
||||
An algorithm can use either a signature algorithm and a hash algorithm pair separated by a
|
||||
`+` (e.g. `ECDSA+SHA224`), or its TLS 1.3 signature scheme name (e.g. `ed25519`).
|
||||
|
||||
Multiple algorithms can be provided by separating them with `:`
|
||||
(e.g. `DSA+SHA256:rsa_pss_pss_sha256`). The parameter is available as `-sigalgs` in the
|
||||
OpenSSL `s_client` and `s_server` utilities.
|
||||
|
||||
`--sigalgs` allows a OpenSSL powered curl to make SSL-connections with exactly
|
||||
the signature algorithms requested by the client, avoiding nontransparent client/server
|
||||
negotiations.
|
||||
|
||||
If this option is set, the default signature algorithm list built into OpenSSL are ignored.
|
||||
@ -1128,6 +1128,10 @@ Control SSL behavior. See CURLOPT_SSL_OPTIONS(3)
|
||||
|
||||
Disable SSL session-id cache. See CURLOPT_SSL_SESSIONID_CACHE(3)
|
||||
|
||||
## CURLOPT_SSL_SIGNATURE_ALGORITHMS
|
||||
|
||||
TLS signature algorithms to use. See CURLOPT_SSL_SIGNATURE_ALGORITHMS(3)
|
||||
|
||||
## CURLOPT_SSL_VERIFYHOST
|
||||
|
||||
Verify the hostname in the SSL certificate. See CURLOPT_SSL_VERIFYHOST(3)
|
||||
|
||||
84
docs/libcurl/opts/CURLOPT_SSL_SIGNATURE_ALGORITHMS.md
Normal file
84
docs/libcurl/opts/CURLOPT_SSL_SIGNATURE_ALGORITHMS.md
Normal file
@ -0,0 +1,84 @@
|
||||
---
|
||||
c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
SPDX-License-Identifier: curl
|
||||
Title: CURLOPT_SSL_SIGNATURE_ALGORITHMS
|
||||
Section: 3
|
||||
Source: libcurl
|
||||
See-also:
|
||||
- CURLOPT_SSL_CIPHER_LIST (3)
|
||||
- CURLOPT_SSL_EC_CURVES (3)
|
||||
- CURLOPT_SSLVERSION (3)
|
||||
- CURLOPT_USE_SSL (3)
|
||||
Protocol:
|
||||
- TLS
|
||||
TLS-backend:
|
||||
- OpenSSL
|
||||
Added-in: 8.14.0
|
||||
---
|
||||
|
||||
# NAME
|
||||
|
||||
CURLOPT_SSL_SIGNATURE_ALGORITHMS - signature algorithms to use for TLS
|
||||
|
||||
# SYNOPSIS
|
||||
|
||||
~~~c
|
||||
#include <curl/curl.h>
|
||||
|
||||
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSL_SIGNATURE_ALGORITHMS, char *list);
|
||||
~~~
|
||||
|
||||
# DESCRIPTION
|
||||
|
||||
Pass a char pointer, pointing to a null-terminated string holding the list of
|
||||
signature algorithms to use for the TLS connection. The list must be syntactically
|
||||
correct, it consists of one or more signature algorithm strings separated by colons.
|
||||
|
||||
A valid example of a signature algorithms list with OpenSSL is:
|
||||
~~~
|
||||
"DSA+SHA256:rsa_pss_pss_sha256"
|
||||
~~~
|
||||
|
||||
The application does not have to keep the string around after setting this
|
||||
option.
|
||||
|
||||
Using this option multiple times makes the last set string override the
|
||||
previous ones. Set it to NULL to disable its use again.
|
||||
|
||||
Works with OpenSSL and its BoringSSL fork (added in 8.14.0).
|
||||
|
||||
# DEFAULT
|
||||
|
||||
NULL, use built-in list
|
||||
|
||||
# %PROTOCOLS%
|
||||
|
||||
# EXAMPLE
|
||||
|
||||
~~~c
|
||||
int main(void)
|
||||
{
|
||||
CURL *curl = curl_easy_init();
|
||||
if(curl) {
|
||||
CURLcode res;
|
||||
curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
|
||||
curl_easy_setopt(curl, CURLOPT_SSL_SIGNATURE_ALGORITHMS,
|
||||
"DSA+SHA256:rsa_pss_pss_sha256");
|
||||
res = curl_easy_perform(curl);
|
||||
curl_easy_cleanup(curl);
|
||||
}
|
||||
}
|
||||
~~~
|
||||
|
||||
# HISTORY
|
||||
|
||||
OpenSSL support added in 8.14.0.
|
||||
|
||||
# %AVAILABILITY%
|
||||
|
||||
# RETURN VALUE
|
||||
|
||||
curl_easy_setopt(3) returns a CURLcode indicating success or error.
|
||||
|
||||
CURLE_OK (0) means everything was OK, non-zero means an error occurred, see
|
||||
libcurl-errors(3).
|
||||
@ -367,6 +367,7 @@ man_MANS = \
|
||||
CURLOPT_SSL_FALSESTART.3 \
|
||||
CURLOPT_SSL_OPTIONS.3 \
|
||||
CURLOPT_SSL_SESSIONID_CACHE.3 \
|
||||
CURLOPT_SSL_SIGNATURE_ALGORITHMS.3 \
|
||||
CURLOPT_SSL_VERIFYHOST.3 \
|
||||
CURLOPT_SSL_VERIFYPEER.3 \
|
||||
CURLOPT_SSL_VERIFYSTATUS.3 \
|
||||
|
||||
@ -849,6 +849,7 @@ CURLOPT_SSL_ENABLE_NPN 7.36.0 7.86.0
|
||||
CURLOPT_SSL_FALSESTART 7.42.0
|
||||
CURLOPT_SSL_OPTIONS 7.25.0
|
||||
CURLOPT_SSL_SESSIONID_CACHE 7.16.0
|
||||
CURLOPT_SSL_SIGNATURE_ALGORITHMS 8.14.0
|
||||
CURLOPT_SSL_VERIFYHOST 7.8.1
|
||||
CURLOPT_SSL_VERIFYPEER 7.4.2
|
||||
CURLOPT_SSL_VERIFYSTATUS 7.41.0
|
||||
|
||||
@ -218,6 +218,7 @@
|
||||
--show-error (-S) 5.9
|
||||
--show-headers (-i) 4.8
|
||||
--silent (-s) 4.0
|
||||
--sigalgs 8.14.0
|
||||
--skip-existing 8.10.0
|
||||
--socks4 7.15.2
|
||||
--socks4a 7.18.0
|
||||
|
||||
@ -2258,6 +2258,9 @@ typedef enum {
|
||||
|
||||
CURLOPT(CURLOPT_UPLOAD_FLAGS, CURLOPTTYPE_LONG, 327),
|
||||
|
||||
/* set TLS supported signature algorithms */
|
||||
CURLOPT(CURLOPT_SSL_SIGNATURE_ALGORITHMS, CURLOPTTYPE_STRINGPOINT, 328),
|
||||
|
||||
CURLOPT_LASTENTRY /* the last unused */
|
||||
} CURLoption;
|
||||
|
||||
|
||||
@ -402,6 +402,8 @@ CURLWARNING(_curl_easy_getinfo_err_curl_off_t,
|
||||
(option) == CURLOPT_SSLKEY || \
|
||||
(option) == CURLOPT_SSLKEYTYPE || \
|
||||
(option) == CURLOPT_SSL_CIPHER_LIST || \
|
||||
(option) == CURLOPT_SSL_EC_CURVES || \
|
||||
(option) == CURLOPT_SSL_SIGNATURE_ALGORITHMS || \
|
||||
(option) == CURLOPT_TLS13_CIPHERS || \
|
||||
(option) == CURLOPT_TLSAUTH_PASSWORD || \
|
||||
(option) == CURLOPT_TLSAUTH_TYPE || \
|
||||
@ -413,7 +415,6 @@ CURLWARNING(_curl_easy_getinfo_err_curl_off_t,
|
||||
(option) == CURLOPT_AWS_SIGV4 || \
|
||||
(option) == CURLOPT_USERPWD || \
|
||||
(option) == CURLOPT_XOAUTH2_BEARER || \
|
||||
(option) == CURLOPT_SSL_EC_CURVES || \
|
||||
0)
|
||||
|
||||
/* evaluates to true if option takes a curl_write_callback argument */
|
||||
|
||||
@ -317,6 +317,8 @@ const struct curl_easyoption Curl_easyopts[] = {
|
||||
{"SSL_FALSESTART", CURLOPT_SSL_FALSESTART, CURLOT_LONG, 0},
|
||||
{"SSL_OPTIONS", CURLOPT_SSL_OPTIONS, CURLOT_VALUES, 0},
|
||||
{"SSL_SESSIONID_CACHE", CURLOPT_SSL_SESSIONID_CACHE, CURLOT_LONG, 0},
|
||||
{"SSL_SIGNATURE_ALGORITHMS", CURLOPT_SSL_SIGNATURE_ALGORITHMS,
|
||||
CURLOT_STRING, 0},
|
||||
{"SSL_VERIFYHOST", CURLOPT_SSL_VERIFYHOST, CURLOT_LONG, 0},
|
||||
{"SSL_VERIFYPEER", CURLOPT_SSL_VERIFYPEER, CURLOT_LONG, 0},
|
||||
{"SSL_VERIFYSTATUS", CURLOPT_SSL_VERIFYSTATUS, CURLOT_LONG, 0},
|
||||
@ -378,6 +380,6 @@ const struct curl_easyoption Curl_easyopts[] = {
|
||||
*/
|
||||
int Curl_easyopts_check(void)
|
||||
{
|
||||
return (CURLOPT_LASTENTRY % 10000) != (327 + 1);
|
||||
return (CURLOPT_LASTENTRY % 10000) != (328 + 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -2393,6 +2393,15 @@ static CURLcode setopt_cptr(struct Curl_easy *data, CURLoption option,
|
||||
*/
|
||||
return Curl_setstropt(&data->set.str[STRING_SSL_EC_CURVES], ptr);
|
||||
|
||||
case CURLOPT_SSL_SIGNATURE_ALGORITHMS:
|
||||
/*
|
||||
* Set accepted signature algorithms.
|
||||
* Specify colon-delimited list of signature scheme names.
|
||||
*/
|
||||
if(Curl_ssl_supports(data, SSLSUPP_SIGNATURE_ALGORITHMS))
|
||||
return Curl_setstropt(&data->set.str[STRING_SSL_SIGNATURE_ALGORITHMS],
|
||||
ptr);
|
||||
return CURLE_NOT_BUILT_IN;
|
||||
#endif
|
||||
#ifdef USE_SSH
|
||||
case CURLOPT_SSH_PUBLIC_KEYFILE:
|
||||
|
||||
@ -265,6 +265,7 @@ struct ssl_primary_config {
|
||||
char *clientcert;
|
||||
char *cipher_list; /* list of ciphers to use */
|
||||
char *cipher_list13; /* list of TLS 1.3 cipher suites to use */
|
||||
char *signature_algorithms; /* list of signature algorithms to use */
|
||||
char *pinned_key;
|
||||
char *CRLfile; /* CRL to check certificate revocation */
|
||||
struct curl_blob *cert_blob;
|
||||
@ -1474,6 +1475,7 @@ enum dupstring {
|
||||
#endif
|
||||
STRING_ECH_CONFIG, /* CURLOPT_ECH_CONFIG */
|
||||
STRING_ECH_PUBLIC, /* CURLOPT_ECH_PUBLIC */
|
||||
STRING_SSL_SIGNATURE_ALGORITHMS, /* CURLOPT_SSL_SIGNATURE_ALGORITHMS */
|
||||
|
||||
/* -- end of null-terminated strings -- */
|
||||
|
||||
|
||||
@ -197,6 +197,16 @@ static void ossl_provider_cleanup(struct Curl_easy *data);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Whether SSL_CTX_set1_sigalgs_list is available
|
||||
* OpenSSL: supported since 1.0.2 (commit 0b362de5f575)
|
||||
* BoringSSL: supported since 0.20240913.0 (commit 826ce15)
|
||||
* LibreSSL: no
|
||||
*/
|
||||
#if (OPENSSL_VERSION_NUMBER >= 0x10002000L && \
|
||||
!defined(LIBRESSL_VERSION_NUMBER))
|
||||
#define HAVE_SSL_CTX_SET1_SIGALGS
|
||||
#endif
|
||||
|
||||
#ifdef LIBRESSL_VERSION_NUMBER
|
||||
#define OSSL_PACKAGE "LibreSSL"
|
||||
#elif defined(OPENSSL_IS_BORINGSSL)
|
||||
@ -3870,6 +3880,21 @@ CURLcode Curl_ossl_ctx_init(struct ossl_ctx *octx,
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_SSL_CTX_SET1_SIGALGS
|
||||
#define OSSL_SIGALG_CAST(x) OSSL_CURVE_CAST(x)
|
||||
{
|
||||
const char *signature_algorithms = conn_config->signature_algorithms;
|
||||
if(signature_algorithms) {
|
||||
if(!SSL_CTX_set1_sigalgs_list(octx->ssl_ctx,
|
||||
OSSL_SIGALG_CAST(signature_algorithms))) {
|
||||
failf(data, "failed setting signature algorithms: '%s'",
|
||||
signature_algorithms);
|
||||
return CURLE_SSL_CIPHER;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef USE_OPENSSL_SRP
|
||||
if(ssl_config->primary.username && Curl_auth_allowed_to_host(data)) {
|
||||
char * const ssl_username = ssl_config->primary.username;
|
||||
@ -5524,6 +5549,9 @@ const struct Curl_ssl Curl_ssl_openssl = {
|
||||
#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
|
||||
SSLSUPP_TLS13_CIPHERSUITES |
|
||||
#endif
|
||||
#ifdef HAVE_SSL_CTX_SET1_SIGALGS
|
||||
SSLSUPP_SIGNATURE_ALGORITHMS |
|
||||
#endif
|
||||
#ifdef USE_ECH_OPENSSL
|
||||
SSLSUPP_ECH |
|
||||
#endif
|
||||
|
||||
@ -215,6 +215,7 @@ match_ssl_primary_config(struct Curl_easy *data,
|
||||
strcasecompare(c1->cipher_list, c2->cipher_list) &&
|
||||
strcasecompare(c1->cipher_list13, c2->cipher_list13) &&
|
||||
strcasecompare(c1->curves, c2->curves) &&
|
||||
strcasecompare(c1->signature_algorithms, c2->signature_algorithms) &&
|
||||
strcasecompare(c1->CRLfile, c2->CRLfile) &&
|
||||
strcasecompare(c1->pinned_key, c2->pinned_key))
|
||||
return TRUE;
|
||||
@ -259,6 +260,7 @@ static bool clone_ssl_primary_config(struct ssl_primary_config *source,
|
||||
CLONE_STRING(cipher_list13);
|
||||
CLONE_STRING(pinned_key);
|
||||
CLONE_STRING(curves);
|
||||
CLONE_STRING(signature_algorithms);
|
||||
CLONE_STRING(CRLfile);
|
||||
#ifdef USE_TLS_SRP
|
||||
CLONE_STRING(username);
|
||||
@ -281,6 +283,7 @@ static void free_primary_ssl_config(struct ssl_primary_config *sslc)
|
||||
Curl_safefree(sslc->ca_info_blob);
|
||||
Curl_safefree(sslc->issuercert_blob);
|
||||
Curl_safefree(sslc->curves);
|
||||
Curl_safefree(sslc->signature_algorithms);
|
||||
Curl_safefree(sslc->CRLfile);
|
||||
#ifdef USE_TLS_SRP
|
||||
Curl_safefree(sslc->username);
|
||||
@ -299,6 +302,8 @@ CURLcode Curl_ssl_easy_config_complete(struct Curl_easy *data)
|
||||
data->set.str[STRING_SSL_CIPHER_LIST];
|
||||
data->set.ssl.primary.cipher_list13 =
|
||||
data->set.str[STRING_SSL_CIPHER13_LIST];
|
||||
data->set.ssl.primary.signature_algorithms =
|
||||
data->set.str[STRING_SSL_SIGNATURE_ALGORITHMS];
|
||||
data->set.ssl.primary.pinned_key =
|
||||
data->set.str[STRING_SSL_PINNEDPUBLICKEY];
|
||||
data->set.ssl.primary.cert_blob = data->set.blobs[BLOB_CERT];
|
||||
|
||||
@ -42,6 +42,7 @@ struct dynbuf;
|
||||
#define SSLSUPP_ECH (1<<7)
|
||||
#define SSLSUPP_CA_CACHE (1<<8)
|
||||
#define SSLSUPP_CIPHER_LIST (1<<9) /* supports TLS 1.0-1.2 ciphersuites */
|
||||
#define SSLSUPP_SIGNATURE_ALGORITHMS (1<<10) /* supports TLS sigalgs */
|
||||
|
||||
#ifdef USE_ECH
|
||||
# include "../curl_base64.h"
|
||||
|
||||
@ -127,6 +127,7 @@ options:
|
||||
CURLOPT_SSLKEYTYPE
|
||||
CURLOPT_SSL_CIPHER_LIST
|
||||
CURLOPT_SSL_EC_CURVES
|
||||
CURLOPT_SSL_SIGNATURE_ALGORIHMS
|
||||
CURLOPT_TLS13_CIPHERS
|
||||
CURLOPT_TLSAUTH_PASSWORD
|
||||
CURLOPT_TLSAUTH_TYPE
|
||||
|
||||
@ -1164,6 +1164,7 @@ curl_easy_setopt_ccsid(CURL *easy, CURLoption tag, ...)
|
||||
case CURLOPT_SSLKEYTYPE:
|
||||
case CURLOPT_SSL_CIPHER_LIST:
|
||||
case CURLOPT_SSL_EC_CURVES:
|
||||
case CURLOPT_SSL_SIGNATURE_ALGORITHMS:
|
||||
case CURLOPT_TLS13_CIPHERS:
|
||||
case CURLOPT_TLSAUTH_PASSWORD:
|
||||
case CURLOPT_TLSAUTH_TYPE:
|
||||
|
||||
@ -135,6 +135,7 @@ struct OperationConfig {
|
||||
char *etag_compare_file;
|
||||
char *customrequest;
|
||||
char *ssl_ec_curves;
|
||||
char *ssl_signature_algorithms;
|
||||
char *krblevel;
|
||||
char *request_target;
|
||||
char *writeout; /* %-styled format string to output */
|
||||
|
||||
@ -305,6 +305,8 @@ static const struct LongShort aliases[]= {
|
||||
{"sessionid", ARG_BOOL|ARG_NO, ' ', C_SESSIONID},
|
||||
{"show-error", ARG_BOOL, 'S', C_SHOW_ERROR},
|
||||
{"show-headers", ARG_BOOL, 'i', C_SHOW_HEADERS},
|
||||
{"sigalgs", ARG_STRG|ARG_TLS, ' ',
|
||||
C_SIGNATURE_ALGORITHMS},
|
||||
{"silent", ARG_BOOL, 's', C_SILENT},
|
||||
{"skip-existing", ARG_BOOL, ' ', C_SKIP_EXISTING},
|
||||
{"socks4", ARG_STRG, ' ', C_SOCKS4},
|
||||
@ -2692,6 +2694,9 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */
|
||||
case C_CURVES: /* --curves */
|
||||
err = getstr(&config->ssl_ec_curves, nextarg, DENY_BLANK);
|
||||
break;
|
||||
case C_SIGNATURE_ALGORITHMS: /* --sigalgs */
|
||||
err = getstr(&config->ssl_signature_algorithms, nextarg, DENY_BLANK);
|
||||
break;
|
||||
case C_FAIL_EARLY: /* --fail-early */
|
||||
global->fail_early = toggle;
|
||||
break;
|
||||
|
||||
@ -242,6 +242,7 @@ typedef enum {
|
||||
C_SHOW_ERROR,
|
||||
C_SHOW_HEADERS,
|
||||
C_SILENT,
|
||||
C_SIGNATURE_ALGORITHMS,
|
||||
C_SKIP_EXISTING,
|
||||
C_SOCKS4,
|
||||
C_SOCKS4A,
|
||||
|
||||
@ -659,6 +659,9 @@ const struct helptxt helptext[] = {
|
||||
{"-i, --show-headers",
|
||||
"Show response headers in output",
|
||||
CURLHELP_IMPORTANT | CURLHELP_VERBOSE | CURLHELP_OUTPUT},
|
||||
{" --sigalgs <list>",
|
||||
"TLS signature algorithms to use",
|
||||
CURLHELP_TLS},
|
||||
{"-s, --silent",
|
||||
"Silent mode",
|
||||
CURLHELP_IMPORTANT | CURLHELP_VERBOSE},
|
||||
|
||||
@ -1263,6 +1263,10 @@ static CURLcode config2setopts(struct GlobalConfig *global,
|
||||
if(config->ssl_ec_curves)
|
||||
my_setopt_str(curl, CURLOPT_SSL_EC_CURVES, config->ssl_ec_curves);
|
||||
|
||||
if(config->ssl_signature_algorithms)
|
||||
my_setopt_str(curl, CURLOPT_SSL_SIGNATURE_ALGORITHMS,
|
||||
config->ssl_signature_algorithms);
|
||||
|
||||
if(config->writeout)
|
||||
my_setopt_long(curl, CURLOPT_CERTINFO, 1);
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user