summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Baentsch <57787676+baentsch@users.noreply.github.com>2020-08-29 14:09:24 +0200
committerDaniel Stenberg <daniel@haxx.se>2020-08-30 17:24:04 +0200
commitede125b7b7ca8fc5a1fe3d7c1aee6bff2ea0bf24 (patch)
treeef1c1fd2071ecad350d6f89b6524d218b1dfe562
parenta337355487c4c3305a4c0703282fdcbe008d4998 (diff)
downloadcurl-ede125b7b7ca8fc5a1fe3d7c1aee6bff2ea0bf24.tar.gz
tls: add CURLOPT_SSL_EC_CURVES and --curves
Closes #5892
-rw-r--r--docs/cmdline-opts/Makefile.inc1
-rw-r--r--docs/cmdline-opts/curves.d17
-rw-r--r--docs/libcurl/curl_easy_setopt.32
-rw-r--r--docs/libcurl/opts/CURLOPT_SSL_EC_CURVES.354
-rw-r--r--docs/libcurl/opts/Makefile.inc1
-rw-r--r--docs/libcurl/symbols-in-versions1
-rw-r--r--docs/options-in-versions1
-rw-r--r--include/curl/curl.h6
-rw-r--r--include/curl/typecheck-gcc.h1
-rw-r--r--lib/doh.c4
-rw-r--r--lib/easyoptions.c3
-rw-r--r--lib/setopt.c8
-rw-r--r--lib/url.c1
-rw-r--r--lib/urldata.h2
-rw-r--r--lib/vtls/openssl.c16
-rw-r--r--lib/vtls/vtls.c3
-rw-r--r--src/tool_cfgable.h1
-rw-r--r--src/tool_getparam.c5
-rw-r--r--src/tool_help.c2
-rw-r--r--src/tool_operate.c3
20 files changed, 131 insertions, 1 deletions
diff --git a/docs/cmdline-opts/Makefile.inc b/docs/cmdline-opts/Makefile.inc
index aa1acabe0..792cadb3c 100644
--- a/docs/cmdline-opts/Makefile.inc
+++ b/docs/cmdline-opts/Makefile.inc
@@ -41,6 +41,7 @@ DPAGES = \
cookie.d \
create-dirs.d \
crlf.d crlfile.d \
+ curves.d \
data-ascii.d \
data-binary.d \
data-urlencode.d \
diff --git a/docs/cmdline-opts/curves.d b/docs/cmdline-opts/curves.d
new file mode 100644
index 000000000..03264c05a
--- /dev/null
+++ b/docs/cmdline-opts/curves.d
@@ -0,0 +1,17 @@
+Long: curves
+Arg: <algorithm list>
+Help: (EC) TLS key exchange algorithm(s) to request
+Protocols: TLS
+Added: 7.73.0
+---
+Tells curl to request specific curves to use during SSL session establishment
+according to RFC 8422, 5.1. Multiple algorithms can be provided by separating
+them with ":" (e.g. "X25519:P-521"). The parameter is available identically
+in the "openssl s_client/s_server" utilities.
+
+--curves allows a OpenSSL powered curl to make SSL-connections with exactly
+the (EC) curve requested by the client, avoiding intransparent client/server
+negotiations.
+
+If this option is set, the default curves list built into openssl will be
+ignored.
diff --git a/docs/libcurl/curl_easy_setopt.3 b/docs/libcurl/curl_easy_setopt.3
index a64375e0c..7f6016614 100644
--- a/docs/libcurl/curl_easy_setopt.3
+++ b/docs/libcurl/curl_easy_setopt.3
@@ -532,6 +532,8 @@ Proxy client key type. See \fICURLOPT_PROXY_SSLKEYTYPE(3)\fP
Client key password. See \fICURLOPT_KEYPASSWD(3)\fP
.IP CURLOPT_PROXY_KEYPASSWD
Proxy client key password. See \fICURLOPT_PROXY_KEYPASSWD(3)\fP
+.IP CURLOPT_SSL_EC_CURVES
+Set key exchange curves. See \fICURLOPT_SSL_EC_CURVES(3)\fP
.IP CURLOPT_SSL_ENABLE_ALPN
Enable use of ALPN. See \fICURLOPT_SSL_ENABLE_ALPN(3)\fP
.IP CURLOPT_SSL_ENABLE_NPN
diff --git a/docs/libcurl/opts/CURLOPT_SSL_EC_CURVES.3 b/docs/libcurl/opts/CURLOPT_SSL_EC_CURVES.3
new file mode 100644
index 000000000..f98f0c17a
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_SSL_EC_CURVES.3
@@ -0,0 +1,54 @@
+.\" **************************************************************************
+.\" * _ _ ____ _
+.\" * Project ___| | | | _ \| |
+.\" * / __| | | | |_) | |
+.\" * | (__| |_| | _ <| |___
+.\" * \___|\___/|_| \_\_____|
+.\" *
+.\" * Copyright (C) 1998 - 2020, 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.haxx.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.
+.\" *
+.\" **************************************************************************
+.\"
+.TH CURLOPT_SSL_EC_CURVES 3 "29 Aug 2020" "libcurl 7.73.0" "curl_easy_setopt options"
+.SH NAME
+CURLOPT_SSL_EC_CURVES \- set key exchange curves
+.SH SYNOPSIS
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSL_EC_CURVES, char *alg_list);
+.SH DESCRIPTION
+Pass a string as parameter with a colon delimited list of (EC) algorithms. This
+option defines the client's key exchange algorithms in the SSL handshake (if
+the SSL backend libcurl is built to use supports it).
+.SH DEFAULT
+"", embedded in SSL backend
+.SH PROTOCOLS
+HTTP
+.SH EXAMPLE
+.nf
+CURL *curl = curl_easy_init();
+if(curl) {
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
+ curl_easy_setopt(curl, CURLOPT_SSL_EC_CURVES, "X25519:P-521");
+ ret = curl_easy_perform(curl);
+ curl_easy_cleanup(curl);
+}
+.fi
+.SH AVAILABILITY
+Added in 7.73.0. Supported by the OpenSSL backend.
+.SH RETURN VALUE
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
+.SH "SEE ALSO"
+.BR CURLOPT_SSL_OPTIONS "(3), " CURLOPT_SSL_CIPHER_LIST "(3), "
+.BR CURLOPT_TLS13_CIPHERS "(3), "
diff --git a/docs/libcurl/opts/Makefile.inc b/docs/libcurl/opts/Makefile.inc
index ebf234002..fe4177579 100644
--- a/docs/libcurl/opts/Makefile.inc
+++ b/docs/libcurl/opts/Makefile.inc
@@ -331,6 +331,7 @@ man_MANS = \
CURLOPT_SSL_CIPHER_LIST.3 \
CURLOPT_SSL_CTX_DATA.3 \
CURLOPT_SSL_CTX_FUNCTION.3 \
+ CURLOPT_SSL_EC_CURVES.3 \
CURLOPT_SSL_ENABLE_ALPN.3 \
CURLOPT_SSL_ENABLE_NPN.3 \
CURLOPT_SSL_FALSESTART.3 \
diff --git a/docs/libcurl/symbols-in-versions b/docs/libcurl/symbols-in-versions
index 82a8e8b3d..74b955093 100644
--- a/docs/libcurl/symbols-in-versions
+++ b/docs/libcurl/symbols-in-versions
@@ -616,6 +616,7 @@ CURLOPT_SSLVERSION 7.1
CURLOPT_SSL_CIPHER_LIST 7.9
CURLOPT_SSL_CTX_DATA 7.10.6
CURLOPT_SSL_CTX_FUNCTION 7.10.6
+CURLOPT_SSL_EC_CURVES 7.73.0
CURLOPT_SSL_ENABLE_ALPN 7.36.0
CURLOPT_SSL_ENABLE_NPN 7.36.0
CURLOPT_SSL_FALSESTART 7.42.0
diff --git a/docs/options-in-versions b/docs/options-in-versions
index ba070a47f..683363239 100644
--- a/docs/options-in-versions
+++ b/docs/options-in-versions
@@ -32,6 +32,7 @@
--create-dirs 7.10.3
--crlf 5.7
--crlfile 7.19.7
+--curves 7.73.0
--data (-d) 4.0
--data-ascii 7.2
--data-binary 7.2
diff --git a/include/curl/curl.h b/include/curl/curl.h
index 32d9bd4a7..9026aa5c1 100644
--- a/include/curl/curl.h
+++ b/include/curl/curl.h
@@ -2025,6 +2025,12 @@ typedef enum {
CURLOPT(CURLOPT_PROXY_ISSUERCERT, CURLOPTTYPE_STRINGPOINT, 296),
CURLOPT(CURLOPT_PROXY_ISSUERCERT_BLOB, CURLOPTTYPE_BLOB, 297),
+ /* the EC curves requested by the TLS client (RFC 8422, 5.1);
+ * OpenSSL support via 'set_groups'/'set_curves':
+ * https://www.openssl.org/docs/manmaster/man3/SSL_CTX_set1_groups.html
+ */
+ CURLOPT(CURLOPT_SSL_EC_CURVES, CURLOPTTYPE_STRINGPOINT, 298),
+
CURLOPT_LASTENTRY /* the last unused */
} CURLoption;
diff --git a/include/curl/typecheck-gcc.h b/include/curl/typecheck-gcc.h
index 4f99ca778..318ab0abb 100644
--- a/include/curl/typecheck-gcc.h
+++ b/include/curl/typecheck-gcc.h
@@ -335,6 +335,7 @@ CURLWARNING(_curl_easy_getinfo_err_curl_off_t,
(option) == CURLOPT_USERNAME || \
(option) == CURLOPT_USERPWD || \
(option) == CURLOPT_XOAUTH2_BEARER || \
+ (option) == CURLOPT_SSL_EC_CURVES || \
0)
/* evaluates to true if option takes a curl_write_callback argument */
diff --git a/lib/doh.c b/lib/doh.c
index 31c243883..e8b080110 100644
--- a/lib/doh.c
+++ b/lib/doh.c
@@ -349,6 +349,10 @@ static CURLcode dohprobe(struct Curl_easy *data,
ERROR_CHECK_SETOPT(CURLOPT_SSL_CTX_FUNCTION, data->set.ssl.fsslctx);
if(data->set.ssl.fsslctxp)
ERROR_CHECK_SETOPT(CURLOPT_SSL_CTX_DATA, data->set.ssl.fsslctxp);
+ if(data->set.str[STRING_SSL_EC_CURVES]) {
+ ERROR_CHECK_SETOPT(CURLOPT_SSL_EC_CURVES,
+ data->set.str[STRING_SSL_EC_CURVES]);
+ }
doh->set.fmultidone = Curl_doh_done;
doh->set.dohfor = data; /* identify for which transfer this is done */
diff --git a/lib/easyoptions.c b/lib/easyoptions.c
index 3294c1d0b..9145ba7fc 100644
--- a/lib/easyoptions.c
+++ b/lib/easyoptions.c
@@ -278,6 +278,7 @@ struct curl_easyoption Curl_easyopts[] = {
{"SSL_CIPHER_LIST", CURLOPT_SSL_CIPHER_LIST, CURLOT_STRING, 0},
{"SSL_CTX_DATA", CURLOPT_SSL_CTX_DATA, CURLOT_CBPTR, 0},
{"SSL_CTX_FUNCTION", CURLOPT_SSL_CTX_FUNCTION, CURLOT_FUNCTION, 0},
+ {"SSL_EC_CURVES", CURLOPT_SSL_EC_CURVES, CURLOT_STRING, 0},
{"SSL_ENABLE_ALPN", CURLOPT_SSL_ENABLE_ALPN, CURLOT_LONG, 0},
{"SSL_ENABLE_NPN", CURLOPT_SSL_ENABLE_NPN, CURLOT_LONG, 0},
{"SSL_FALSESTART", CURLOPT_SSL_FALSESTART, CURLOT_LONG, 0},
@@ -341,6 +342,6 @@ struct curl_easyoption Curl_easyopts[] = {
*/
int Curl_easyopts_check(void)
{
- return (CURLOPT_LASTENTRY != (297 + 1));
+ return (CURLOPT_LASTENTRY != (298 + 1));
}
#endif
diff --git a/lib/setopt.c b/lib/setopt.c
index 6631c13fe..ef6c7cb9a 100644
--- a/lib/setopt.c
+++ b/lib/setopt.c
@@ -2241,6 +2241,14 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
break;
#endif
+ case CURLOPT_SSL_EC_CURVES:
+ /*
+ * Set accepted curves in SSL connection setup.
+ * Specify colon-delimited list of curve algorithm names.
+ */
+ result = Curl_setstropt(&data->set.str[STRING_SSL_EC_CURVES],
+ va_arg(param, char *));
+ break;
#endif
case CURLOPT_IPRESOLVE:
arg = va_arg(param, long);
diff --git a/lib/url.c b/lib/url.c
index 086de88af..2f879a61c 100644
--- a/lib/url.c
+++ b/lib/url.c
@@ -3616,6 +3616,7 @@ static CURLcode create_conn(struct Curl_easy *data,
data->set.ssl.primary.pinned_key =
data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG];
data->set.ssl.primary.cert_blob = data->set.blobs[BLOB_CERT_ORIG];
+ data->set.ssl.primary.curves = data->set.str[STRING_SSL_EC_CURVES];
#ifndef CURL_DISABLE_PROXY
data->set.proxy_ssl.primary.CApath = data->set.str[STRING_SSL_CAPATH_PROXY];
diff --git a/lib/urldata.h b/lib/urldata.h
index 86f8af42c..f9ac93a86 100644
--- a/lib/urldata.h
+++ b/lib/urldata.h
@@ -230,6 +230,7 @@ struct ssl_primary_config {
char *cipher_list13; /* list of TLS 1.3 cipher suites to use */
char *pinned_key;
struct curl_blob *cert_blob;
+ char *curves; /* list of curves to use */
BIT(verifypeer); /* set TRUE if this is desired */
BIT(verifyhost); /* set TRUE if CN/SAN must match hostname */
BIT(verifystatus); /* set TRUE if certificate status must be checked */
@@ -1565,6 +1566,7 @@ enum dupstring {
STRING_DNS_INTERFACE,
STRING_DNS_LOCAL_IP4,
STRING_DNS_LOCAL_IP6,
+ STRING_SSL_EC_CURVES,
/* -- end of null-terminated strings -- */
diff --git a/lib/vtls/openssl.c b/lib/vtls/openssl.c
index 09f331418..ce6f8445a 100644
--- a/lib/vtls/openssl.c
+++ b/lib/vtls/openssl.c
@@ -200,6 +200,10 @@
!defined(OPENSSL_IS_BORINGSSL))
#define HAVE_SSL_CTX_SET_CIPHERSUITES
#define HAVE_SSL_CTX_SET_POST_HANDSHAKE_AUTH
+/* SET_EC_CURVES available under the same preconditions: see
+ * https://www.openssl.org/docs/manmaster/man3/SSL_CTX_set1_groups.html
+ */
+#define HAVE_SSL_CTX_SET_EC_CURVES
#endif
#if defined(LIBRESSL_VERSION_NUMBER)
@@ -2800,6 +2804,18 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
SSL_CTX_set_post_handshake_auth(backend->ctx, 1);
#endif
+#ifdef HAVE_SSL_CTX_SET_EC_CURVES
+ {
+ char *curves = SSL_CONN_CONFIG(curves);
+ if(curves) {
+ if(!SSL_CTX_set1_curves_list(backend->ctx, curves)) {
+ failf(data, "failed setting curves list: '%s'", curves);
+ return CURLE_SSL_CIPHER;
+ }
+ }
+ }
+#endif
+
#ifdef HAVE_OPENSSL_SRP
if(ssl_authtype == CURL_TLSAUTH_SRP) {
char * const ssl_username = SSL_SET_OPTION(username);
diff --git a/lib/vtls/vtls.c b/lib/vtls/vtls.c
index 281043aa6..9db4fd0ef 100644
--- a/lib/vtls/vtls.c
+++ b/lib/vtls/vtls.c
@@ -138,6 +138,7 @@ Curl_ssl_config_matches(struct ssl_primary_config *data,
Curl_safe_strcasecompare(data->egdsocket, needle->egdsocket) &&
Curl_safe_strcasecompare(data->cipher_list, needle->cipher_list) &&
Curl_safe_strcasecompare(data->cipher_list13, needle->cipher_list13) &&
+ Curl_safe_strcasecompare(data->curves, needle->curves) &&
Curl_safe_strcasecompare(data->pinned_key, needle->pinned_key))
return TRUE;
@@ -164,6 +165,7 @@ Curl_clone_primary_ssl_config(struct ssl_primary_config *source,
CLONE_STRING(cipher_list);
CLONE_STRING(cipher_list13);
CLONE_STRING(pinned_key);
+ CLONE_STRING(curves);
return TRUE;
}
@@ -179,6 +181,7 @@ void Curl_free_primary_ssl_config(struct ssl_primary_config *sslc)
Curl_safefree(sslc->cipher_list13);
Curl_safefree(sslc->pinned_key);
Curl_safefree(sslc->cert_blob);
+ Curl_safefree(sslc->curves);
}
#ifdef USE_SSL
diff --git a/src/tool_cfgable.h b/src/tool_cfgable.h
index 620bfef3e..a3b8dd51b 100644
--- a/src/tool_cfgable.h
+++ b/src/tool_cfgable.h
@@ -162,6 +162,7 @@ struct OperationConfig {
char *etag_compare_file;
bool crlf;
char *customrequest;
+ char *ssl_ec_curves;
char *krblevel;
char *request_target;
long httpversion;
diff --git a/src/tool_getparam.c b/src/tool_getparam.c
index 74b6b7369..64c988122 100644
--- a/src/tool_getparam.c
+++ b/src/tool_getparam.c
@@ -272,6 +272,7 @@ static const struct LongShort aliases[]= {
{"EB", "socks5-gssapi", ARG_BOOL},
{"EC", "etag-save", ARG_FILENAME},
{"ED", "etag-compare", ARG_FILENAME},
+ {"EE", "curves", ARG_STRING},
{"f", "fail", ARG_BOOL},
{"fa", "fail-early", ARG_BOOL},
{"fb", "styled-output", ARG_BOOL},
@@ -1726,6 +1727,10 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */
GetStr(&config->etag_compare_file, nextarg);
break;
+ case 'E':
+ GetStr(&config->ssl_ec_curves, nextarg);
+ break;
+
default: /* unknown flag */
return PARAM_OPTION_UNKNOWN;
}
diff --git a/src/tool_help.c b/src/tool_help.c
index 29680d05a..c8b2f52c9 100644
--- a/src/tool_help.c
+++ b/src/tool_help.c
@@ -94,6 +94,8 @@ static const struct helptxt helptext[] = {
"Convert LF to CRLF in upload"},
{" --crlfile <file>",
"Get a CRL list in PEM format from the given file"},
+ {" --curves <algorithm list>",
+ "(EC) TLS key exchange algorithm(s) to request "},
{"-d, --data <data>",
"HTTP POST data"},
{" --data-ascii <data>",
diff --git a/src/tool_operate.c b/src/tool_operate.c
index aaadeeb9d..1fe7637d2 100644
--- a/src/tool_operate.c
+++ b/src/tool_operate.c
@@ -1520,6 +1520,9 @@ static CURLcode single_transfer(struct GlobalConfig *global,
if(config->pinnedpubkey)
my_setopt_str(curl, CURLOPT_PINNEDPUBLICKEY, config->pinnedpubkey);
+ if(config->ssl_ec_curves)
+ my_setopt_str(curl, CURLOPT_SSL_EC_CURVES, config->ssl_ec_curves);
+
if(curlinfo->features & CURL_VERSION_SSL) {
/* Check if config->cert is a PKCS#11 URI and set the
* config->cert_type if necessary */