From: Nikos Mavrogiannopoulos Date: Thu, 15 Oct 2015 16:20:38 +0000 (+0200) Subject: Tolerate priority strings with names of legacy ciphers and key exchanges X-Git-Tag: gnutls_3_5_0~640 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b237b37d4d17ee4f98629aae9d72aec87f434cb8;p=thirdparty%2Fgnutls.git Tolerate priority strings with names of legacy ciphers and key exchanges That enables better backwards compatibility with old applications which disable or enable algorithms which no longer are supported. Relates #44 --- diff --git a/lib/algorithms.h b/lib/algorithms.h index 9dcfc01160..9959ccea42 100644 --- a/lib/algorithms.h +++ b/lib/algorithms.h @@ -273,6 +273,8 @@ int _gnutls_kx_needs_rsa_params(gnutls_kx_algorithm_t algorithm); mod_auth_st *_gnutls_kx_auth_struct(gnutls_kx_algorithm_t algorithm); int _gnutls_kx_is_ok(gnutls_kx_algorithm_t algorithm); +int _gnutls_kx_get_id(const char *name); + /* Type to KX mappings. */ gnutls_kx_algorithm_t _gnutls_map_kx_get_kx(gnutls_credentials_type_t type, int server); diff --git a/lib/algorithms/ciphers.c b/lib/algorithms/ciphers.c index 1c5529c507..e69f54f38f 100644 --- a/lib/algorithms/ciphers.c +++ b/lib/algorithms/ciphers.c @@ -31,7 +31,9 @@ * View first: "The order of encryption and authentication for * protecting communications" by Hugo Krawczyk - CRYPTO 2001 * - * Make sure to update MAX_CIPHER_BLOCK_SIZE and MAX_CIPHER_KEY_SIZE as well. + * On update, make sure to update MAX_CIPHER_BLOCK_SIZE and MAX_CIPHER_KEY_SIZE + * as well. If any ciphers are removed, modify the is_legacy() functions + * in priority.c. */ static const cipher_entry_st algorithms[] = { { .name = "AES-256-CBC", @@ -229,13 +231,14 @@ const cipher_entry_st *cipher_to_entry(gnutls_cipher_algorithm_t c) return NULL; } -const cipher_entry_st * cipher_name_to_entry(const char *name) +/* Returns cipher entry even for ciphers that are not supported, + * but are listed (e.g., deprecated ciphers). + */ +const cipher_entry_st *cipher_name_to_entry(const char *name) { GNUTLS_CIPHER_LOOP( if (strcasecmp(p->name, name) == 0) { - if (p->id == GNUTLS_CIPHER_NULL || _gnutls_cipher_exists(p->id)) - return p; - break; + return p; } ); diff --git a/lib/algorithms/kx.c b/lib/algorithms/kx.c index 6373f930a0..9f83a6074a 100644 --- a/lib/algorithms/kx.c +++ b/lib/algorithms/kx.c @@ -124,6 +124,7 @@ static const gnutls_kx_algo_entry _gnutls_kx_algorithms[] = { {"ECDHE-PSK", GNUTLS_KX_ECDHE_PSK, &ecdhe_psk_auth_struct, 0, GNUTLS_PK_UNKNOWN}, #endif #endif + {"RSA-EXPORT", GNUTLS_KX_INVALID, NULL, 0, GNUTLS_PK_UNKNOWN}, {0, 0, 0, 0, 0} }; @@ -190,6 +191,24 @@ gnutls_kx_algorithm_t gnutls_kx_get_id(const char *name) { gnutls_kx_algorithm_t ret = GNUTLS_KX_UNKNOWN; + GNUTLS_KX_LOOP( + if (strcasecmp(p->name, name) == 0 && p->algorithm != GNUTLS_KX_INVALID) { + ret = p->algorithm; + break; + } + ); + + return ret; +} + +/* As with gnutls_kx_get_id(), but it returns all known + * key exchange algorithms (even legacy), with GNUTLS_KX_INVALID + * value. + */ +int _gnutls_kx_get_id(const char *name) +{ + gnutls_kx_algorithm_t ret = GNUTLS_KX_UNKNOWN; + GNUTLS_KX_LOOP( if (strcasecmp(p->name, name) == 0) { ret = p->algorithm; diff --git a/lib/gnutls_int.h b/lib/gnutls_int.h index 083834b89f..75b5f4dd8c 100644 --- a/lib/gnutls_int.h +++ b/lib/gnutls_int.h @@ -214,6 +214,8 @@ typedef enum record_flush_t { #define GNUTLS_POINTER_TO_INT(_) ((int) GNUTLS_POINTER_TO_INT_CAST (_)) #define GNUTLS_INT_TO_POINTER(_) ((void*) GNUTLS_POINTER_TO_INT_CAST (_)) +#define GNUTLS_KX_INVALID (-1) + typedef struct { uint8_t pint[3]; } uint24; diff --git a/lib/priority.c b/lib/priority.c index 6b6339f0ec..bb9493401f 100644 --- a/lib/priority.c +++ b/lib/priority.c @@ -1142,17 +1142,20 @@ gnutls_priority_init(gnutls_priority_t * priority_cache, continue; } else if ((algo = gnutls_mac_get_id(&broken_list[i][1])) - != GNUTLS_MAC_UNKNOWN) + != GNUTLS_MAC_UNKNOWN) { fn(&(*priority_cache)->mac, algo); - else if ((centry = cipher_name_to_entry(&broken_list[i][1])) != NULL) { - fn(&(*priority_cache)->cipher, centry->id); - if (centry->type == CIPHER_BLOCK) - (*priority_cache)->have_cbc = 1; + } else if ((centry = cipher_name_to_entry(&broken_list[i][1])) != NULL) { + if (_gnutls_cipher_exists(centry->id)) { + fn(&(*priority_cache)->cipher, centry->id); + if (centry->type == CIPHER_BLOCK) + (*priority_cache)->have_cbc = 1; + } } else if ((algo = - gnutls_kx_get_id(&broken_list[i][1])) != - GNUTLS_KX_UNKNOWN) - fn(&(*priority_cache)->kx, algo); - else if (strncasecmp + _gnutls_kx_get_id(&broken_list[i][1])) != + GNUTLS_KX_UNKNOWN) { + if (algo != GNUTLS_KX_INVALID) + fn(&(*priority_cache)->kx, algo); + } else if (strncasecmp (&broken_list[i][1], "VERS-", 5) == 0) { if (strncasecmp (&broken_list[i][1], "VERS-TLS-ALL",