summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--crypto/src/tls/AbstractTlsServer.cs43
-rw-r--r--crypto/src/tls/NamedGroup.cs2
2 files changed, 29 insertions, 16 deletions
diff --git a/crypto/src/tls/AbstractTlsServer.cs b/crypto/src/tls/AbstractTlsServer.cs
index f445ac18d..7e8c26ffd 100644
--- a/crypto/src/tls/AbstractTlsServer.cs
+++ b/crypto/src/tls/AbstractTlsServer.cs
@@ -69,37 +69,48 @@ namespace Org.BouncyCastle.Tls
 
         protected virtual int GetMaximumNegotiableCurveBits()
         {
+            int maxBits = 0;
             int[] clientSupportedGroups = m_context.SecurityParameters.ClientSupportedGroups;
-            if (clientSupportedGroups == null)
+            if (clientSupportedGroups != null)
+            {
+                for (int i = 0; i < clientSupportedGroups.Length; ++i)
+                {
+                    maxBits = System.Math.Max(maxBits, NamedGroup.GetCurveBits(clientSupportedGroups[i]));
+                }
+            }
+            else
             {
                 /*
                  * RFC 4492 4. A client that proposes ECC cipher suites may choose not to include these
-                 * extensions. In this case, the server is free to choose any one of the elliptic curves
-                 * or point formats [...].
+                 * extensions. In this case, the server is free to choose any one of the elliptic curves or point
+                 * formats [...].
                  */
-                return NamedGroup.GetMaximumCurveBits();
-            }
-
-            int maxBits = 0;
-            for (int i = 0; i < clientSupportedGroups.Length; ++i)
-            {
-                maxBits = System.Math.Max(maxBits, NamedGroup.GetCurveBits(clientSupportedGroups[i]));
+                maxBits = NamedGroup.GetMaximumCurveBits();
             }
             return maxBits;
         }
 
         protected virtual int GetMaximumNegotiableFiniteFieldBits()
         {
+            int maxBits = 0;
+            bool anyPeerFF = false;
             int[] clientSupportedGroups = m_context.SecurityParameters.ClientSupportedGroups;
-            if (clientSupportedGroups == null)
+            if (clientSupportedGroups != null)
             {
-                return NamedGroup.GetMaximumFiniteFieldBits();
+                for (int i = 0; i < clientSupportedGroups.Length; ++i)
+                {
+                    anyPeerFF |= NamedGroup.IsFiniteField(clientSupportedGroups[i]);
+                    maxBits = System.Math.Max(maxBits, NamedGroup.GetFiniteFieldBits(clientSupportedGroups[i]));
+                }
             }
-
-            int maxBits = 0;
-            for (int i = 0; i < clientSupportedGroups.Length; ++i)
+            if (!anyPeerFF)
             {
-                maxBits = System.Math.Max(maxBits, NamedGroup.GetFiniteFieldBits(clientSupportedGroups[i]));
+                /*
+                 * RFC 7919 4. If [...] the Supported Groups extension is either absent from the ClientHello
+                 * entirely or contains no FFDHE groups (i.e., no codepoints between 256 and 511, inclusive), then
+                 * the server [...] MAY select an FFDHE cipher suite and offer an FFDHE group of its choice [...].
+                 */
+                maxBits = NamedGroup.GetMaximumFiniteFieldBits();
             }
             return maxBits;
         }
diff --git a/crypto/src/tls/NamedGroup.cs b/crypto/src/tls/NamedGroup.cs
index 0035ef9f3..15671a837 100644
--- a/crypto/src/tls/NamedGroup.cs
+++ b/crypto/src/tls/NamedGroup.cs
@@ -358,6 +358,8 @@ namespace Org.BouncyCastle.Tls
                 || (namedGroup == arbitrary_explicit_char2_curves);
         }
 
+        public static bool IsFiniteField(int namedGroup) => (namedGroup & 0xFFFFFF00) == 0x00000100;
+
         public static bool IsPrimeCurve(int namedGroup)
         {
             return (namedGroup >= secp160k1 && namedGroup <= curveSM2)