diff --git a/libratbox/src/mbedtls.c b/libratbox/src/mbedtls.c index 8435942e..b3c9678d 100644 --- a/libratbox/src/mbedtls.c +++ b/libratbox/src/mbedtls.c @@ -442,19 +442,18 @@ rb_setup_ssl_server(const char *const certfile, const char *keyfile, return 0; } + + + const int *rb_ciphersuites = newcfg->suites; + size_t suites_count = 0; + if(cipherlist != NULL) { // The cipherlist is (const char *) -- we should not modify it char *const cipherlist_dup = strdup(cipherlist); - if(cipherlist_dup == NULL) + if(cipherlist_dup != NULL) { - rb_lib_log("rb_setup_ssl_server: strdup: %s", strerror(errno)); - rb_lib_log("rb_setup_ssl_server: will not configure ciphersuites!"); - } - else - { - size_t suites_count = 0; char *cipher_str = cipherlist_dup; char *cipher_idx; @@ -489,18 +488,34 @@ rb_setup_ssl_server(const char *const certfile, const char *keyfile, } while(cipher_idx && suites_count < RB_MAX_CIPHERSUITES); - if(suites_count > 0) - { - mbedtls_ssl_conf_ciphersuites(&newcfg->server_cfg, newcfg->suites); - mbedtls_ssl_conf_ciphersuites(&newcfg->client_cfg, newcfg->suites); - rb_lib_log("rb_setup_ssl_server: Configured %zu ciphersuites", suites_count); - } - else - rb_lib_log("rb_setup_ssl_server: Passed a list of ciphersuites, but could not configure any"); + if(suites_count == 0) + rb_lib_log("rb_setup_ssl_server: Ciphersuites provided, but could not parse any"); free(cipherlist_dup); } + else + { + rb_lib_log("rb_setup_ssl_server: strdup: %s", strerror(errno)); + } } + else + { + rb_lib_log("rb_setup_ssl_server: No ciphersuite list provided"); + } + + if(suites_count == 0) + { + rb_lib_log("rb_setup_ssl_server: Using default ciphersuites"); + + rb_ciphersuites = rb_mbedtls_ciphersuites; + suites_count = sizeof(rb_mbedtls_ciphersuites) / sizeof(rb_mbedtls_ciphersuites[0]); + } + + mbedtls_ssl_conf_ciphersuites(&newcfg->server_cfg, rb_ciphersuites); + mbedtls_ssl_conf_ciphersuites(&newcfg->client_cfg, rb_ciphersuites); + rb_lib_log("rb_setup_ssl_server: Configured %zu ciphersuites", suites_count); + + rb_mbedtls_cfg_decref(rb_mbedtls_cfg); rb_mbedtls_cfg = newcfg; diff --git a/libratbox/src/mbedtls_embedded_data.h b/libratbox/src/mbedtls_embedded_data.h index 83782089..4eb7ca81 100644 --- a/libratbox/src/mbedtls_embedded_data.h +++ b/libratbox/src/mbedtls_embedded_data.h @@ -25,11 +25,90 @@ #ifndef RB_MBEDTLS_EMBEDDED_DATA_H #define RB_MBEDTLS_EMBEDDED_DATA_H +#include "mbedtls/ssl_ciphersuites.h" + /* * Personalization string for CTR-DRBG initialization */ static const char rb_mbedtls_personal_str[] = "charybdis/librb personalization string"; +/* + * Default list of supported ciphersuites + * User can override with ssl_cipher_list option in ircd.conf + * + * Charybdis cannot have more than one certificate configured, which means that with + * the MbedTLS backend, it will ALWAYS be serving EITHER an RSA OR ECDSA certificate. + * + * This means we can order ciphersuites to place all ECDSA ones ahead of RSA ones, + * without weird interactions of cipher order, such as inadvertantly preferring an + * ECDSA ciphersuite with AES128-CBC-SHA over an RSA ciphersuite with + * AES256-GCM-SHA384. + * + * We also prefer all AEAD ciphersuites first, even if it results in using a 128-bit + * AEAD ciphersuite instead of a 256-bit CBC ciphersuite. This is due to the fact that + * ONLY the AEAD ciphersuites in TLS are cryptographically secure in practice; the ETM + * extension for CBC ciphersuites has not seen wide adoption. This choice can be + * revisited in future; please consult me first. -- amdj + */ +static const int rb_mbedtls_ciphersuites[] = { + + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, + MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384, + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM, + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, + MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256, + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM, + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, + MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384, + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, + MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256, + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, + + MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, + MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384, + MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256, + MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, + MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384, + MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, + MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, + MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256, + MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, + + MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, + MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384, + MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM, + MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, + MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256, + MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA, + MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA, + MBEDTLS_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, + MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256, + MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM, + MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, + MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256, + MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA, + MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA, + + MBEDTLS_TLS_RSA_WITH_AES_256_GCM_SHA384, + MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384, + MBEDTLS_TLS_RSA_WITH_AES_256_CCM, + MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256, + MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256, + MBEDTLS_TLS_RSA_WITH_AES_128_CCM, + MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA256, + MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256, + MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA, + MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA, + MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA256, + MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256, + MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA, + MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA, + + 0 // End of list +}; + /* * YES, this is a hardcoded CA certificate. *