summary refs log tree commit diff
path: root/crypto/src/tls/TlsEccUtilities.cs
diff options
context:
space:
mode:
Diffstat (limited to 'crypto/src/tls/TlsEccUtilities.cs')
-rw-r--r--crypto/src/tls/TlsEccUtilities.cs117
1 files changed, 117 insertions, 0 deletions
diff --git a/crypto/src/tls/TlsEccUtilities.cs b/crypto/src/tls/TlsEccUtilities.cs
new file mode 100644
index 000000000..59320a717
--- /dev/null
+++ b/crypto/src/tls/TlsEccUtilities.cs
@@ -0,0 +1,117 @@
+using System;
+using System.IO;
+
+using Org.BouncyCastle.Tls.Crypto;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Tls
+{
+    public abstract class TlsEccUtilities
+    {
+        /// <exception cref="IOException"/>
+        public static TlsECConfig CreateNamedECConfig(TlsContext context, int namedGroup)
+        {
+            if (NamedGroup.GetCurveBits(namedGroup) < 1)
+                throw new TlsFatalAlert(AlertDescription.internal_error);
+
+            return new TlsECConfig(namedGroup);
+        }
+
+        public static int GetMinimumCurveBits(int cipherSuite)
+        {
+            /*
+             * NOTE: This mechanism was added to support a minimum bit-size requirement mooted in early
+             * drafts of RFC 8442. This requirement was removed in later drafts, so this mechanism is
+             * currently somewhat trivial.
+             */
+            return IsEccCipherSuite(cipherSuite) ? 1 : 0;
+        }
+
+        public static bool IsEccCipherSuite(int cipherSuite)
+        {
+            switch (TlsUtilities.GetKeyExchangeAlgorithm(cipherSuite))
+            {
+            case KeyExchangeAlgorithm.ECDH_anon:
+            case KeyExchangeAlgorithm.ECDH_ECDSA:
+            case KeyExchangeAlgorithm.ECDH_RSA:
+            case KeyExchangeAlgorithm.ECDHE_ECDSA:
+            case KeyExchangeAlgorithm.ECDHE_PSK:
+            case KeyExchangeAlgorithm.ECDHE_RSA:
+                return true;
+
+            default:
+                return false;
+            }
+        }
+
+        /// <exception cref="IOException"/>
+        public static void CheckPointEncoding(int namedGroup, byte[] encoding)
+        {
+            if (TlsUtilities.IsNullOrEmpty(encoding))
+                throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+
+            switch (namedGroup)
+            {
+            case NamedGroup.x25519:
+            case NamedGroup.x448:
+                return;
+            }
+
+            switch (encoding[0])
+            {
+            case 0x04: // uncompressed
+                return;
+
+            case 0x00: // infinity
+            case 0x02: // compressed
+            case 0x03: // compressed
+            case 0x06: // hybrid
+            case 0x07: // hybrid
+            default:
+                throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+            }
+        }
+
+        /// <exception cref="IOException"/>
+        public static TlsECConfig ReceiveECDHConfig(TlsContext context, Stream input)
+        {
+            short curveType = TlsUtilities.ReadUint8(input);
+            if (curveType != ECCurveType.named_curve)
+                throw new TlsFatalAlert(AlertDescription.handshake_failure);
+
+            int namedGroup = TlsUtilities.ReadUint16(input);
+            if (NamedGroup.RefersToAnECDHCurve(namedGroup))
+            {
+                int[] clientSupportedGroups = context.SecurityParameters.ClientSupportedGroups;
+                if (null == clientSupportedGroups || Arrays.Contains(clientSupportedGroups, namedGroup))
+                    return new TlsECConfig(namedGroup);
+            }
+
+            throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+        }
+
+        /// <exception cref="IOException"/>
+        public static void WriteECConfig(TlsECConfig ecConfig, Stream output)
+        {
+            WriteNamedECParameters(ecConfig.NamedGroup, output);
+        }
+
+        /// <exception cref="IOException"/>
+        public static void WriteNamedECParameters(int namedGroup, Stream output)
+        {
+            if (!NamedGroup.RefersToASpecificCurve(namedGroup))
+            {
+                /*
+                 * RFC 4492 5.4. All those values of NamedCurve are allowed that refer to a specific
+                 * curve. Values of NamedCurve that indicate support for a class of explicitly defined
+                 * curves are not allowed here [...].
+                 */
+                throw new TlsFatalAlert(AlertDescription.internal_error);
+            }
+
+            TlsUtilities.WriteUint8(ECCurveType.named_curve, output);
+            TlsUtilities.CheckUint16(namedGroup);
+            TlsUtilities.WriteUint16(namedGroup, output);
+        }
+    }
+}