tls-crypto: Fallback to any supported ECDH group
authorTobias Brunner <tobias@strongswan.org>
Thu, 11 Feb 2021 16:46:17 +0000 (17:46 +0100)
committerTobias Brunner <tobias@strongswan.org>
Fri, 12 Feb 2021 13:35:23 +0000 (14:35 +0100)
If the default group listed in the cipher suite is not supported, we try
to use any other supported group (the groups are negotiated separately
so we are not locked in to a specific group).

src/libtls/tls_crypto.c

index d7faa4e..ed1eea3 100644 (file)
@@ -1418,19 +1418,6 @@ METHOD(tls_crypto_t, select_cipher_suite, tls_cipher_suite_t,
        return 0;
 }
 
-METHOD(tls_crypto_t, get_dh_group, diffie_hellman_group_t,
-       private_tls_crypto_t *this)
-{
-       suite_algs_t *algs;
-
-       algs = find_suite(this->suite);
-       if (algs)
-       {
-               return algs->dh;
-       }
-       return MODP_NONE;
-}
-
 /**
  * Parameters for RSA/PSS signature schemes
  */
@@ -1629,6 +1616,7 @@ CALLBACK(config_filter, bool,
        while (orig->enumerate(orig, &group, &curve))
        {
                if (filter_curve_config(curve))
+
                {
                        if (group_out)
                        {
@@ -1654,6 +1642,50 @@ METHOD(tls_crypto_t, create_ec_enumerator, enumerator_t*,
                                                        config_filter, NULL, NULL);
 }
 
+/**
+ * Check if the given ECDH group is supported or return the first one we
+ * actually do support.
+ */
+static diffie_hellman_group_t supported_ec_group(private_tls_crypto_t *this,
+                                                                                                diffie_hellman_group_t orig)
+{
+       diffie_hellman_group_t current, first = MODP_NONE;
+       enumerator_t *enumerator;
+
+       enumerator = create_ec_enumerator(this);
+       while (enumerator->enumerate(enumerator, &current, NULL))
+       {
+               if (current == orig)
+               {
+                       enumerator->destroy(enumerator);
+                       return orig;
+               }
+               else if (first == MODP_NONE)
+               {
+                       first = current;
+               }
+       }
+       enumerator->destroy(enumerator);
+       return first;
+}
+
+METHOD(tls_crypto_t, get_dh_group, diffie_hellman_group_t,
+       private_tls_crypto_t *this)
+{
+       suite_algs_t *algs;
+
+       algs = find_suite(this->suite);
+       if (algs)
+       {
+               if (diffie_hellman_group_is_ec(algs->dh))
+               {
+                       return supported_ec_group(this, algs->dh);
+               }
+               return algs->dh;
+       }
+       return MODP_NONE;
+}
+
 METHOD(tls_crypto_t, set_protection, void,
        private_tls_crypto_t *this, tls_protection_t *protection)
 {