]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
Tolerate priority strings with names of legacy ciphers and key exchanges
authorNikos Mavrogiannopoulos <nmav@redhat.com>
Thu, 15 Oct 2015 16:20:38 +0000 (18:20 +0200)
committerNikos Mavrogiannopoulos <nmav@redhat.com>
Thu, 15 Oct 2015 16:21:36 +0000 (18:21 +0200)
That enables better backwards compatibility with old applications
which disable or enable algorithms which no longer are supported.
Relates #44

lib/algorithms.h
lib/algorithms/ciphers.c
lib/algorithms/kx.c
lib/gnutls_int.h
lib/priority.c

index 9dcfc011602670437dd823532e86042a71689a39..9959ccea42e7fa77327c9a5763300fb599c96839 100644 (file)
@@ -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);
index 1c5529c50772d967b6622cefa207bd9913b2391c..e69f54f38f22105b614025f597ebe7863df4e711 100644 (file)
@@ -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;
                }
        );
 
index 6373f930a08da1eff52f758d78ad3de3a69d9a40..9f83a6074a3e9332a8135c424495438c60b41d5f 100644 (file)
@@ -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;
index 083834b89f607fc192ccf1397b116d1116bf145f..75b5f4dd8c441f6409ca5373a72d03ad6bc90212 100644 (file)
@@ -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;
index 6b6339f0ec48e5d9a5b7cf60451acd00cc1f486d..bb9493401f132c967f7caff45398c3bd11c98a6e 100644 (file)
@@ -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",