Specify the supported curves with TLS

This commit is contained in:
Willem Toorop 2018-02-12 15:40:17 +01:00
parent e944203e55
commit 401aa2e3b8
6 changed files with 115 additions and 2 deletions

View File

@ -1,4 +1,8 @@
* 2018-0?-??: Version 1.?.?
* Specify the supported curves with getdns_context_set_tls_curves_list()
An upstream specific list of supported curves may also be given
with the tls_curves_list setting in the upstream dict with
getdns_context_set_upstream_recursive_servers()
* libidn2 support. Thanks Paul Wouters
* 2017-12-21: Version 1.3.0

View File

@ -409,7 +409,7 @@ AC_CHECK_HEADERS([openssl/conf.h],,, [AC_INCLUDES_DEFAULT])
AC_CHECK_HEADERS([openssl/engine.h],,, [AC_INCLUDES_DEFAULT])
AC_CHECK_HEADERS([openssl/bn.h openssl/rsa.h openssl/dsa.h],,, [AC_INCLUDES_DEFAULT])
AC_CHECK_FUNCS([OPENSSL_config EVP_md5 EVP_sha1 EVP_sha224 EVP_sha256 EVP_sha384 EVP_sha512 FIPS_mode ENGINE_load_cryptodev EVP_PKEY_keygen ECDSA_SIG_get0 EVP_MD_CTX_new EVP_PKEY_base_id HMAC_CTX_new HMAC_CTX_free TLS_client_method DSA_SIG_set0 EVP_dss1 EVP_DigestVerify SSL_CTX_set_min_proto_version OpenSSL_version_num OpenSSL_version])
AC_CHECK_DECLS([SSL_COMP_get_compression_methods,sk_SSL_COMP_pop_free,SSL_CTX_set_ecdh_auto], [], [], [
AC_CHECK_DECLS([SSL_COMP_get_compression_methods,sk_SSL_COMP_pop_free,SSL_CTX_set_ecdh_auto,SSL_CTX_set1_curves_list,SSL_set1_curves_list], [], [], [
AC_INCLUDES_DEFAULT
#ifdef HAVE_OPENSSL_ERR_H
#include <openssl/err.h>

View File

@ -738,6 +738,8 @@ _getdns_upstreams_dereference(getdns_upstreams *upstreams)
upstream->tls_pubkey_pinset = NULL;
if (upstream->tls_cipher_list)
GETDNS_FREE(upstreams->mf, upstream->tls_cipher_list);
if (upstream->tls_curves_list)
GETDNS_FREE(upstreams->mf, upstream->tls_curves_list);
}
GETDNS_FREE(upstreams->mf, upstreams);
}
@ -1022,6 +1024,7 @@ upstream_init(getdns_upstream *upstream,
upstream->tls_obj = NULL;
upstream->tls_session = NULL;
upstream->tls_cipher_list = NULL;
upstream->tls_curves_list = NULL;
upstream->transport = GETDNS_TRANSPORT_TCP;
upstream->tls_hs_state = GETDNS_HS_NONE;
upstream->tls_auth_name[0] = '\0';
@ -1535,6 +1538,7 @@ getdns_context_create_with_extended_memory_functions(
result->tls_ca_path = NULL;
result->tls_ca_file = NULL;
result->tls_cipher_list = NULL;
result->tls_curves_list = NULL;
(void) memset(&result->root_ksk, 0, sizeof(result->root_ksk));
@ -1805,6 +1809,8 @@ getdns_context_destroy(struct getdns_context *context)
GETDNS_FREE(context->mf, context->tls_ca_file);
if (context->tls_cipher_list)
GETDNS_FREE(context->mf, context->tls_cipher_list);
if (context->tls_curves_list)
GETDNS_FREE(context->mf, context->tls_curves_list);
#ifdef USE_WINSOCK
WSACleanup();
@ -2996,6 +3002,7 @@ getdns_context_set_upstream_recursive_servers(struct getdns_context *context,
if (dict && getdns_upstream_transports[j] == GETDNS_TRANSPORT_TLS) {
getdns_list *pubkey_pinset = NULL;
getdns_bindata *tls_cipher_list = NULL;
getdns_bindata *tls_curves_list = NULL;
if ((r = getdns_dict_get_bindata(
dict, "tls_auth_name", &tls_auth_name)) == GETDNS_RETURN_GOOD) {
@ -3007,6 +3014,7 @@ getdns_context_set_upstream_recursive_servers(struct getdns_context *context,
* into account, should not
* be larger than 1024 bytes.
*/
freeaddrinfo(ai);
goto invalid_parameter;
}
memcpy(upstream->tls_auth_name,
@ -3022,15 +3030,30 @@ getdns_context_set_upstream_recursive_servers(struct getdns_context *context,
r = _getdns_get_pubkey_pinset_from_list(pubkey_pinset,
&(upstreams->mf),
&(upstream->tls_pubkey_pinset));
if (r != GETDNS_RETURN_GOOD)
if (r != GETDNS_RETURN_GOOD) {
freeaddrinfo(ai);
goto invalid_parameter;
}
}
(void) getdns_dict_get_bindata(
dict, "tls_cipher_list", &tls_cipher_list);
upstream->tls_cipher_list = tls_cipher_list
? _getdns_strdup2(&upstreams->mf
, tls_cipher_list)
: NULL;
(void) getdns_dict_get_bindata(
dict, "tls_curves_list", &tls_curves_list);
if (tls_curves_list) {
#if defined(HAVE_DECL_SSL_SET1_CURVES_LIST) && HAVE_DECL_SSL_SET1_CURVES_LIST
upstream->tls_curves_list =
_getdns_strdup2(&upstreams->mf
, tls_curves_list);
#else
freeaddrinfo(ai);
goto not_implemented;
#endif
} else
upstream->tls_curves_list = NULL;
}
if ((upstream->tsig_alg = tsig_alg)) {
if (tsig_name) {
@ -3068,6 +3091,11 @@ invalid_parameter:
error:
_getdns_upstreams_dereference(upstreams);
return GETDNS_RETURN_CONTEXT_UPDATE_FAIL;
#if !defined(HAVE_DECL_SSL_SET1_CURVES_LIST) || !HAVE_DECL_SSL_SET1_CURVES_LIST
not_implemented:
_getdns_upstreams_dereference(upstreams);
return GETDNS_RETURN_NOT_IMPLEMENTED;
#endif
} /* getdns_context_set_upstream_recursive_servers */
@ -3608,6 +3636,12 @@ _getdns_context_prepare_for_resolution(getdns_context *context)
context->tls_cipher_list ? context->tls_cipher_list
: _getdns_default_tls_cipher_list))
return GETDNS_RETURN_BAD_CONTEXT;
# if defined(HAVE_DECL_SSL_CTX_SET1_CURVES_LIST) && HAVE_DECL_SSL_CTX_SET1_CURVES_LIST
if (context->tls_curves_list &&
!SSL_CTX_set1_curves_list(context->tls_ctx, context->tls_curves_list))
return GETDNS_RETURN_BAD_CONTEXT;
# endif
/* For strict authentication, we must have local root certs available
Set up is done only when the tls_ctx is created (per getdns_context)*/
if ((context->tls_ca_file || context->tls_ca_path) &&
@ -3924,6 +3958,8 @@ _get_context_settings(getdns_context* context)
(void) getdns_dict_util_set_string(result, "tls_ca_file", str_value);
if (!getdns_context_get_tls_cipher_list(context, &str_value) && str_value)
(void) getdns_dict_util_set_string(result, "tls_cipher_list", str_value);
if (!getdns_context_get_tls_curves_list(context, &str_value) && str_value)
(void) getdns_dict_util_set_string(result, "tls_curves_list", str_value);
/* Default settings for extensions */
(void)getdns_dict_set_int(
@ -4513,6 +4549,11 @@ getdns_context_get_upstream_recursive_servers(getdns_context *context,
d, "tls_cipher_list",
upstream->tls_cipher_list);
}
if (upstream->tls_curves_list) {
(void) getdns_dict_util_set_string(
d, "tls_curves_list",
upstream->tls_curves_list);
}
}
}
if (!r)
@ -4722,6 +4763,7 @@ _getdns_context_config_setting(getdns_context *context,
CONTEXT_SETTING_STRING(tls_ca_path)
CONTEXT_SETTING_STRING(tls_ca_file)
CONTEXT_SETTING_STRING(tls_cipher_list)
CONTEXT_SETTING_STRING(tls_curves_list)
/**************************************/
/**** ****/
@ -5301,5 +5343,35 @@ getdns_context_get_tls_cipher_list(
return GETDNS_RETURN_GOOD;
}
getdns_return_t
getdns_context_set_tls_curves_list(
getdns_context *context, const char *tls_curves_list)
{
if (!context)
return GETDNS_RETURN_INVALID_PARAMETER;
#if defined(HAVE_DECL_SSL_CTX_SET1_CURVES_LIST) && HAVE_DECL_SSL_CTX_SET1_CURVES_LIST
if (context->tls_curves_list)
GETDNS_FREE(context->mf, context->tls_curves_list);
context->tls_curves_list = tls_curves_list
? _getdns_strdup(&context->mf, tls_curves_list)
: NULL;
dispatch_updated(context, GETDNS_CONTEXT_CODE_TLS_CIPHER_LIST);
return GETDNS_RETURN_GOOD;
#else
(void)tls_curves_list;
return GETDNS_RETURN_NOT_IMPLEMENTED;
#endif
}
getdns_return_t
getdns_context_get_tls_curves_list(
getdns_context *context, const char **tls_curves_list)
{
if (!context || !tls_curves_list)
return GETDNS_RETURN_INVALID_PARAMETER;
*tls_curves_list = context->tls_curves_list;
return GETDNS_RETURN_GOOD;
}
/* context.c */

View File

@ -206,6 +206,7 @@ typedef struct getdns_upstream {
getdns_auth_state_t tls_auth_state;
unsigned tls_fallback_ok : 1;
char *tls_cipher_list;
char *tls_curves_list;
/* Auth credentials*/
char tls_auth_name[256];
sha256_pin_t *tls_pubkey_pinset;
@ -347,6 +348,7 @@ struct getdns_context {
char *tls_ca_path;
char *tls_ca_file;
char *tls_cipher_list;
char *tls_curves_list;
getdns_upstreams *upstreams;
uint16_t limit_outstanding_queries;

View File

@ -100,6 +100,8 @@ extern "C" {
#define GETDNS_CONTEXT_CODE_TLS_CA_FILE_TEXT "Change related to getdns_context_set_tls_ca_file"
#define GETDNS_CONTEXT_CODE_TLS_CIPHER_LIST 633
#define GETDNS_CONTEXT_CODE_TLS_CIPHER_LIST_TEXT "Change related to getdns_context_set_tls_cipher_list"
#define GETDNS_CONTEXT_CODE_TLS_CURVES_LIST 634
#define GETDNS_CONTEXT_CODE_TLS_CURVES_LIST_TEXT "Change related to getdns_context_set_tls_curves_list"
/** @}
*/
@ -753,6 +755,20 @@ getdns_return_t
getdns_context_set_tls_cipher_list(
getdns_context *context, const char *cipher_list);
/**
* Sets the supported curves TLS upstreams.
* @see getdns_context_get_tls_curves_list
* @param[in] context The context to configure
* @param[in] curves_list The string is a colon separated list of curve
* NIDs or names, for example "P-521:P-384:P-256".
* @return GETDNS_RETURN_GOOD when successful
* @return GETDNS_RETURN_INVALID_PARAMETER when context was NULL.
*/
getdns_return_t
getdns_context_set_tls_curves_list(
getdns_context *context, const char *curves_list);
/**
* Get the current resolution type setting from this context.
* @see getdns_context_set_resolution_type
@ -1272,6 +1288,21 @@ getdns_return_t
getdns_context_get_tls_cipher_list(
getdns_context *context, const char **cipher_list);
/**
* Get the supported curves list if one has been set earlier.
* @see getdns_context_set_tls_curves_list
* @param[in] context The configured context
* @param[out] curves_list The string is a colon separated list of curve
* NIDs or names, for example "P-521:P-384:P-256",
* when one has been configured on the context,
* or NULL when none has been set before.
* @return GETDNS_RETURN_GOOD when successful
* @return GETDNS_RETURN_INVALID_PARAMETER when context was NULL.
*/
getdns_return_t
getdns_context_get_tls_curves_list(
getdns_context *context, const char **curves_list);
/** @}
*/

View File

@ -925,6 +925,10 @@ tls_create_object(getdns_dns_req *dnsreq, int fd, getdns_upstream *upstream)
SSL_free(ssl);
return NULL;
}
#if defined(HAVE_DECL_SSL_SET1_CURVES_LIST) && HAVE_DECL_SSL_SET1_CURVES_LIST
if (upstream->tls_curves_list)
(void) SSL_set1_curves_list(ssl, upstream->tls_curves_list);
#endif
/* make sure we'll be able to find the context again when we need it */
if (_getdns_associate_upstream_with_SSL(ssl, upstream) != GETDNS_RETURN_GOOD) {
SSL_free(ssl);