mirror of
https://github.com/curl/curl.git
synced 2026-08-24 19:23:38 +03:00
parent
3055c4c814
commit
f5d79619b1
4 changed files with 295 additions and 1 deletions
|
|
@ -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…
Add table
Add a link
Reference in a new issue