mirror of
https://github.com/curl/curl.git
synced 2025-04-12 16:20:35 +08:00
parent
3055c4c814
commit
f5d79619b1
@ -520,3 +520,61 @@ to [constrain the set of available ciphers as specified in the schannel
|
||||
documentation](https://docs.microsoft.com/en-us/windows/win32/secauthn/tls-cipher-suites-in-windows-server-2022).
|
||||
Note that the supported ciphers in this case follow the OS version, so if you
|
||||
are running an outdated OS you might still be supporting weak ciphers.
|
||||
|
||||
## BearSSL
|
||||
|
||||
BearSSL ciphers can be specified by either the OpenSSL name (`ECDHE-RSA-AES128-GCM-SHA256`) or the IANA name (`TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256`).
|
||||
|
||||
Since BearSSL 0.1:
|
||||
|
||||
`DES-CBC3-SHA`
|
||||
`AES128-SHA`
|
||||
`AES256-SHA`
|
||||
`AES128-SHA256`
|
||||
`AES256-SHA256`
|
||||
`AES128-GCM-SHA256`
|
||||
`AES256-GCM-SHA384`
|
||||
`ECDH-ECDSA-DES-CBC3-SHA`
|
||||
`ECDH-ECDSA-AES128-SHA`
|
||||
`ECDH-ECDSA-AES256-SHA`
|
||||
`ECDHE-ECDSA-DES-CBC3-SHA`
|
||||
`ECDHE-ECDSA-AES128-SHA`
|
||||
`ECDHE-ECDSA-AES256-SHA`
|
||||
`ECDH-RSA-DES-CBC3-SHA`
|
||||
`ECDH-RSA-AES128-SHA`
|
||||
`ECDH-RSA-AES256-SHA`
|
||||
`ECDHE-RSA-DES-CBC3-SHA`
|
||||
`ECDHE-RSA-AES128-SHA`
|
||||
`ECDHE-RSA-AES256-SHA`
|
||||
`ECDHE-ECDSA-AES128-SHA256`
|
||||
`ECDHE-ECDSA-AES256-SHA384`
|
||||
`ECDH-ECDSA-AES128-SHA256`
|
||||
`ECDH-ECDSA-AES256-SHA384`
|
||||
`ECDHE-RSA-AES128-SHA256`
|
||||
`ECDHE-RSA-AES256-SHA384`
|
||||
`ECDH-RSA-AES128-SHA256`
|
||||
`ECDH-RSA-AES256-SHA384`
|
||||
`ECDHE-ECDSA-AES128-GCM-SHA256`
|
||||
`ECDHE-ECDSA-AES256-GCM-SHA384`
|
||||
`ECDH-ECDSA-AES128-GCM-SHA256`
|
||||
`ECDH-ECDSA-AES256-GCM-SHA384`
|
||||
`ECDHE-RSA-AES128-GCM-SHA256`
|
||||
`ECDHE-RSA-AES256-GCM-SHA384`
|
||||
`ECDH-RSA-AES128-GCM-SHA256`
|
||||
`ECDH-RSA-AES256-GCM-SHA384`
|
||||
|
||||
Since BearSSL 0.2:
|
||||
|
||||
`ECDHE-RSA-CHACHA20-POLY1305`
|
||||
`ECDHE-ECDSA-CHACHA20-POLY1305`
|
||||
|
||||
Since BearSSL 0.6:
|
||||
|
||||
`AES128-CCM`
|
||||
`AES256-CCM`
|
||||
`AES128-CCM8`
|
||||
`AES256-CCM8`
|
||||
`ECDHE-ECDSA-AES128-CCM`
|
||||
`ECDHE-ECDSA-AES256-CCM`
|
||||
`ECDHE-ECDSA-AES128-CCM8`
|
||||
`ECDHE-ECDSA-AES256-CCM8`
|
||||
|
@ -49,6 +49,13 @@ enabled.
|
||||
For WolfSSL, valid examples of cipher lists include \fBECDHE-RSA-RC4-SHA\fP,
|
||||
\fBAES256-SHA:AES256-SHA256\fP, etc.
|
||||
|
||||
For BearSSL, valid examples of cipher lists include
|
||||
\fBECDHE-RSA-CHACHA20-POLY1305:ECDHE-RSA-AES128-GCM-SHA256\fP, or when using IANA names
|
||||
\fBTLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256:TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256\fP,
|
||||
etc.
|
||||
With BearSSL you do not add/remove ciphers. If one uses this option then all
|
||||
known ciphers are disabled and only those passed in are enabled.
|
||||
|
||||
you will find more details about cipher lists on this URL:
|
||||
|
||||
https://curl.se/docs/ssl-ciphers.html
|
||||
@ -71,7 +78,7 @@ if(curl) {
|
||||
}
|
||||
.fi
|
||||
.SH AVAILABILITY
|
||||
Added in 7.52.0
|
||||
Added in 7.52.0, in 7.83.0 for BearSSL
|
||||
|
||||
If built TLS enabled.
|
||||
.SH RETURN VALUE
|
||||
|
@ -48,6 +48,13 @@ enabled.
|
||||
For WolfSSL, valid examples of cipher lists include \fBECDHE-RSA-RC4-SHA\fP,
|
||||
\fBAES256-SHA:AES256-SHA256\fP, etc.
|
||||
|
||||
For BearSSL, valid examples of cipher lists include
|
||||
\fBECDHE-RSA-CHACHA20-POLY1305:ECDHE-RSA-AES128-GCM-SHA256\fP, or when using IANA names
|
||||
\fBTLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256:TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256\fP,
|
||||
etc.
|
||||
With BearSSL you do not add/remove ciphers. If one uses this option then all
|
||||
known ciphers are disabled and only those passed in are enabled.
|
||||
|
||||
you will find more details about cipher lists on this URL:
|
||||
|
||||
https://curl.se/docs/ssl-ciphers.html
|
||||
@ -69,6 +76,8 @@ if(curl) {
|
||||
}
|
||||
.fi
|
||||
.SH AVAILABILITY
|
||||
Added in 7.9, in 7.83.0 for BearSSL
|
||||
|
||||
If built TLS enabled.
|
||||
.SH RETURN VALUE
|
||||
Returns CURLE_OK if TLS is supported, CURLE_UNKNOWN_OPTION if not, or
|
||||
|
@ -35,6 +35,7 @@
|
||||
#include "multiif.h"
|
||||
#include "curl_printf.h"
|
||||
#include "curl_memory.h"
|
||||
#include "strcase.h"
|
||||
|
||||
struct x509_context {
|
||||
const br_x509_class *vtable;
|
||||
@ -353,6 +354,216 @@ static const br_x509_class x509_vtable = {
|
||||
x509_get_pkey
|
||||
};
|
||||
|
||||
struct st_cipher {
|
||||
const char *name; /* Cipher suite IANA name. It starts with "TLS_" prefix */
|
||||
const char *alias_name; /* Alias name is the same as OpenSSL cipher name */
|
||||
uint16_t num; /* BearSSL cipher suite */
|
||||
};
|
||||
|
||||
/* Macro to initialize st_cipher data structure */
|
||||
#define CIPHER_DEF(num, alias) { #num, alias, BR_##num }
|
||||
|
||||
static const struct st_cipher ciphertable[] = {
|
||||
/* RFC 2246 TLS 1.0 */
|
||||
CIPHER_DEF(TLS_RSA_WITH_3DES_EDE_CBC_SHA, /* 0x000A */
|
||||
"DES-CBC3-SHA"),
|
||||
|
||||
/* RFC 3268 TLS 1.0 AES */
|
||||
CIPHER_DEF(TLS_RSA_WITH_AES_128_CBC_SHA, /* 0x002F */
|
||||
"AES128-SHA"),
|
||||
CIPHER_DEF(TLS_RSA_WITH_AES_256_CBC_SHA, /* 0x0035 */
|
||||
"AES256-SHA"),
|
||||
|
||||
/* RFC 5246 TLS 1.2 */
|
||||
CIPHER_DEF(TLS_RSA_WITH_AES_128_CBC_SHA256, /* 0x003C */
|
||||
"AES128-SHA256"),
|
||||
CIPHER_DEF(TLS_RSA_WITH_AES_256_CBC_SHA256, /* 0x003D */
|
||||
"AES256-SHA256"),
|
||||
|
||||
/* RFC 5288 TLS 1.2 AES GCM */
|
||||
CIPHER_DEF(TLS_RSA_WITH_AES_128_GCM_SHA256, /* 0x009C */
|
||||
"AES128-GCM-SHA256"),
|
||||
CIPHER_DEF(TLS_RSA_WITH_AES_256_GCM_SHA384, /* 0x009D */
|
||||
"AES256-GCM-SHA384"),
|
||||
|
||||
/* RFC 4492 TLS 1.0 ECC */
|
||||
CIPHER_DEF(TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, /* 0xC003 */
|
||||
"ECDH-ECDSA-DES-CBC3-SHA"),
|
||||
CIPHER_DEF(TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, /* 0xC004 */
|
||||
"ECDH-ECDSA-AES128-SHA"),
|
||||
CIPHER_DEF(TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, /* 0xC005 */
|
||||
"ECDH-ECDSA-AES256-SHA"),
|
||||
CIPHER_DEF(TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, /* 0xC008 */
|
||||
"ECDHE-ECDSA-DES-CBC3-SHA"),
|
||||
CIPHER_DEF(TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, /* 0xC009 */
|
||||
"ECDHE-ECDSA-AES128-SHA"),
|
||||
CIPHER_DEF(TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, /* 0xC00A */
|
||||
"ECDHE-ECDSA-AES256-SHA"),
|
||||
CIPHER_DEF(TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, /* 0xC00D */
|
||||
"ECDH-RSA-DES-CBC3-SHA"),
|
||||
CIPHER_DEF(TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, /* 0xC00E */
|
||||
"ECDH-RSA-AES128-SHA"),
|
||||
CIPHER_DEF(TLS_ECDH_RSA_WITH_AES_256_CBC_SHA, /* 0xC00F */
|
||||
"ECDH-RSA-AES256-SHA"),
|
||||
CIPHER_DEF(TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, /* 0xC012 */
|
||||
"ECDHE-RSA-DES-CBC3-SHA"),
|
||||
CIPHER_DEF(TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, /* 0xC013 */
|
||||
"ECDHE-RSA-AES128-SHA"),
|
||||
CIPHER_DEF(TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, /* 0xC014 */
|
||||
"ECDHE-RSA-AES256-SHA"),
|
||||
|
||||
/* RFC 5289 TLS 1.2 ECC HMAC SHA256/384 */
|
||||
CIPHER_DEF(TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, /* 0xC023 */
|
||||
"ECDHE-ECDSA-AES128-SHA256"),
|
||||
CIPHER_DEF(TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, /* 0xC024 */
|
||||
"ECDHE-ECDSA-AES256-SHA384"),
|
||||
CIPHER_DEF(TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256, /* 0xC025 */
|
||||
"ECDH-ECDSA-AES128-SHA256"),
|
||||
CIPHER_DEF(TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384, /* 0xC026 */
|
||||
"ECDH-ECDSA-AES256-SHA384"),
|
||||
CIPHER_DEF(TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, /* 0xC027 */
|
||||
"ECDHE-RSA-AES128-SHA256"),
|
||||
CIPHER_DEF(TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, /* 0xC028 */
|
||||
"ECDHE-RSA-AES256-SHA384"),
|
||||
CIPHER_DEF(TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256, /* 0xC029 */
|
||||
"ECDH-RSA-AES128-SHA256"),
|
||||
CIPHER_DEF(TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384, /* 0xC02A */
|
||||
"ECDH-RSA-AES256-SHA384"),
|
||||
|
||||
/* RFC 5289 TLS 1.2 GCM */
|
||||
CIPHER_DEF(TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, /* 0xC02B */
|
||||
"ECDHE-ECDSA-AES128-GCM-SHA256"),
|
||||
CIPHER_DEF(TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, /* 0xC02C */
|
||||
"ECDHE-ECDSA-AES256-GCM-SHA384"),
|
||||
CIPHER_DEF(TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256, /* 0xC02D */
|
||||
"ECDH-ECDSA-AES128-GCM-SHA256"),
|
||||
CIPHER_DEF(TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384, /* 0xC02E */
|
||||
"ECDH-ECDSA-AES256-GCM-SHA384"),
|
||||
CIPHER_DEF(TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, /* 0xC02F */
|
||||
"ECDHE-RSA-AES128-GCM-SHA256"),
|
||||
CIPHER_DEF(TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, /* 0xC030 */
|
||||
"ECDHE-RSA-AES256-GCM-SHA384"),
|
||||
CIPHER_DEF(TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256, /* 0xC031 */
|
||||
"ECDH-RSA-AES128-GCM-SHA256"),
|
||||
CIPHER_DEF(TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384, /* 0xC032 */
|
||||
"ECDH-RSA-AES256-GCM-SHA384"),
|
||||
#ifdef BR_TLS_RSA_WITH_AES_128_CCM
|
||||
|
||||
/* RFC 6655 TLS 1.2 CCM
|
||||
Supported since BearSSL 0.6 */
|
||||
CIPHER_DEF(TLS_RSA_WITH_AES_128_CCM, /* 0xC09C */
|
||||
"AES128-CCM"),
|
||||
CIPHER_DEF(TLS_RSA_WITH_AES_256_CCM, /* 0xC09D */
|
||||
"AES256-CCM"),
|
||||
CIPHER_DEF(TLS_RSA_WITH_AES_128_CCM_8, /* 0xC0A0 */
|
||||
"AES128-CCM8"),
|
||||
CIPHER_DEF(TLS_RSA_WITH_AES_256_CCM_8, /* 0xC0A1 */
|
||||
"AES256-CCM8"),
|
||||
|
||||
/* RFC 7251 TLS 1.2 ECC CCM
|
||||
Supported since BearSSL 0.6 */
|
||||
CIPHER_DEF(TLS_ECDHE_ECDSA_WITH_AES_128_CCM, /* 0xC0AC */
|
||||
"ECDHE-ECDSA-AES128-CCM"),
|
||||
CIPHER_DEF(TLS_ECDHE_ECDSA_WITH_AES_256_CCM, /* 0xC0AD */
|
||||
"ECDHE-ECDSA-AES256-CCM"),
|
||||
CIPHER_DEF(TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8, /* 0xC0AE */
|
||||
"ECDHE-ECDSA-AES128-CCM8"),
|
||||
CIPHER_DEF(TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8, /* 0xC0AF */
|
||||
"ECDHE-ECDSA-AES256-CCM8"),
|
||||
#endif
|
||||
|
||||
/* RFC 7905 TLS 1.2 ChaCha20-Poly1305
|
||||
Supported since BearSSL 0.2 */
|
||||
CIPHER_DEF(TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, /* 0xCCA8 */
|
||||
"ECDHE-RSA-CHACHA20-POLY1305"),
|
||||
CIPHER_DEF(TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, /* 0xCCA9 */
|
||||
"ECDHE-ECDSA-CHACHA20-POLY1305"),
|
||||
};
|
||||
|
||||
#define NUM_OF_CIPHERS (sizeof(ciphertable) / sizeof(ciphertable[0]))
|
||||
#define CIPHER_NAME_BUF_LEN 64
|
||||
|
||||
static bool is_separator(char c)
|
||||
{
|
||||
/* Return whether character is a cipher list separator. */
|
||||
switch(c) {
|
||||
case ' ':
|
||||
case '\t':
|
||||
case ':':
|
||||
case ',':
|
||||
case ';':
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static CURLcode bearssl_set_selected_ciphers(struct Curl_easy *data,
|
||||
br_ssl_engine_context *ssl_eng,
|
||||
const char *ciphers)
|
||||
{
|
||||
uint16_t selected_ciphers[NUM_OF_CIPHERS];
|
||||
size_t selected_count = 0;
|
||||
char cipher_name[CIPHER_NAME_BUF_LEN];
|
||||
const char *cipher_start = ciphers;
|
||||
const char *cipher_end;
|
||||
size_t i, j;
|
||||
|
||||
if(!cipher_start)
|
||||
return CURLE_SSL_CIPHER;
|
||||
|
||||
while(true) {
|
||||
/* Extract the next cipher name from the ciphers string */
|
||||
while(is_separator(*cipher_start))
|
||||
++cipher_start;
|
||||
if(*cipher_start == '\0')
|
||||
break;
|
||||
cipher_end = cipher_start;
|
||||
while(*cipher_end != '\0' && !is_separator(*cipher_end))
|
||||
++cipher_end;
|
||||
j = cipher_end - cipher_start < CIPHER_NAME_BUF_LEN - 1 ?
|
||||
cipher_end - cipher_start : CIPHER_NAME_BUF_LEN - 1;
|
||||
strncpy(cipher_name, cipher_start, j);
|
||||
cipher_name[j] = '\0';
|
||||
cipher_start = cipher_end;
|
||||
|
||||
/* Lookup the cipher name in the table of available ciphers. If the cipher
|
||||
name starts with "TLS_" we do the lookup by IANA name. Otherwise, we try
|
||||
to match cipher name by an (OpenSSL) alias. */
|
||||
if(strncasecompare(cipher_name, "TLS_", 4)) {
|
||||
for(i = 0; i < NUM_OF_CIPHERS &&
|
||||
!strcasecompare(cipher_name, ciphertable[i].name); ++i);
|
||||
}
|
||||
else {
|
||||
for(i = 0; i < NUM_OF_CIPHERS &&
|
||||
!strcasecompare(cipher_name, ciphertable[i].alias_name); ++i);
|
||||
}
|
||||
if(i == NUM_OF_CIPHERS) {
|
||||
infof(data, "BearSSL: unknown cipher in list: %s", cipher_name);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* No duplicates allowed */
|
||||
for(j = 0; j < selected_count &&
|
||||
selected_ciphers[j] != ciphertable[i].num; j++);
|
||||
if(j < selected_count) {
|
||||
infof(data, "BearSSL: duplicate cipher in list: %s", cipher_name);
|
||||
continue;
|
||||
}
|
||||
|
||||
DEBUGASSERT(selected_count < NUM_OF_CIPHERS);
|
||||
selected_ciphers[selected_count] = ciphertable[i].num;
|
||||
++selected_count;
|
||||
}
|
||||
|
||||
if(selected_count == 0) {
|
||||
failf(data, "BearSSL: no supported cipher in list");
|
||||
return CURLE_SSL_CIPHER;
|
||||
}
|
||||
|
||||
br_ssl_engine_set_suites(ssl_eng, selected_ciphers, selected_count);
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
static CURLcode bearssl_connect_step1(struct Curl_easy *data,
|
||||
struct connectdata *conn, int sockindex)
|
||||
{
|
||||
@ -446,6 +657,15 @@ static CURLcode bearssl_connect_step1(struct Curl_easy *data,
|
||||
br_ssl_engine_set_buffer(&backend->ctx.eng, backend->buf,
|
||||
sizeof(backend->buf), 1);
|
||||
|
||||
if(SSL_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() */
|
||||
ret = bearssl_set_selected_ciphers(data, &backend->ctx.eng,
|
||||
SSL_CONN_CONFIG(cipher_list));
|
||||
if(ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* initialize X.509 context */
|
||||
backend->x509.vtable = &x509_vtable;
|
||||
backend->x509.verifypeer = verifypeer;
|
||||
|
Loading…
x
Reference in New Issue
Block a user