From 976b61455215febd86c902024cb054cfe05975f0 Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Wed, 1 Nov 2023 16:13:16 +0700 Subject: TLS: Improve supported_groups compliance --- crypto/src/tls/AbstractTlsServer.cs | 43 +++++++++++++++++++++++-------------- crypto/src/tls/NamedGroup.cs | 2 ++ 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) -- cgit 1.4.1