summary refs log tree commit diff
path: root/crypto
diff options
context:
space:
mode:
authorPeter Dettman <peter.dettman@bouncycastle.org>2018-07-24 15:27:51 +0700
committerPeter Dettman <peter.dettman@bouncycastle.org>2018-07-24 15:27:51 +0700
commitc0ee6b45d8764144f3a5b36d286e7520d35b63e7 (patch)
treec71c2787c31f76749d80cbfe9b383bfd7898451b /crypto
parentIDEA: Update patent information (diff)
downloadBouncyCastle.NET-ed25519-c0ee6b45d8764144f3a5b36d286e7520d35b63e7.tar.xz
TLS: Use DH group whitelisting
Diffstat (limited to 'crypto')
-rw-r--r--crypto/BouncyCastle.Android.csproj3
-rw-r--r--crypto/BouncyCastle.csproj3
-rw-r--r--crypto/BouncyCastle.iOS.csproj3
-rw-r--r--crypto/crypto.csproj15
-rw-r--r--crypto/src/crypto/tls/DefaultTlsClient.cs16
-rw-r--r--crypto/src/crypto/tls/DefaultTlsDHVerifier.cs101
-rw-r--r--crypto/src/crypto/tls/DefaultTlsServer.cs4
-rw-r--r--crypto/src/crypto/tls/PskTlsClient.cs15
-rw-r--r--crypto/src/crypto/tls/PskTlsServer.cs2
-rw-r--r--crypto/src/crypto/tls/ServerDHParams.cs61
-rw-r--r--crypto/src/crypto/tls/TlsDHKeyExchange.cs32
-rw-r--r--crypto/src/crypto/tls/TlsDHUtilities.cs43
-rw-r--r--crypto/src/crypto/tls/TlsDHVerifier.cs15
-rw-r--r--crypto/src/crypto/tls/TlsDheKeyExchange.cs11
-rw-r--r--crypto/src/crypto/tls/TlsPskKeyExchange.cs15
15 files changed, 196 insertions, 143 deletions
diff --git a/crypto/BouncyCastle.Android.csproj b/crypto/BouncyCastle.Android.csproj
index a9ddae8d8..3c34c5e1b 100644
--- a/crypto/BouncyCastle.Android.csproj
+++ b/crypto/BouncyCastle.Android.csproj
@@ -1002,6 +1002,7 @@
     <Compile Include="src\crypto\tls\DefaultTlsAgreementCredentials.cs" />
     <Compile Include="src\crypto\tls\DefaultTlsCipherFactory.cs" />
     <Compile Include="src\crypto\tls\DefaultTlsClient.cs" />
+    <Compile Include="src\crypto\tls\DefaultTlsDHVerifier.cs" />
     <Compile Include="src\crypto\tls\DefaultTlsEncryptionCredentials.cs" />
     <Compile Include="src\crypto\tls\DefaultTlsServer.cs" />
     <Compile Include="src\crypto\tls\DefaultTlsSignerCredentials.cs" />
@@ -1045,7 +1046,6 @@
     <Compile Include="src\crypto\tls\PskTlsServer.cs" />
     <Compile Include="src\crypto\tls\RecordStream.cs" />
     <Compile Include="src\crypto\tls\SecurityParameters.cs" />
-    <Compile Include="src\crypto\tls\ServerDHParams.cs" />
     <Compile Include="src\crypto\tls\ServerName.cs" />
     <Compile Include="src\crypto\tls\ServerNameList.cs" />
     <Compile Include="src\crypto\tls\ServerOnlyTlsAuthentication.cs" />
@@ -1076,6 +1076,7 @@
     <Compile Include="src\crypto\tls\TlsCredentials.cs" />
     <Compile Include="src\crypto\tls\TlsDHKeyExchange.cs" />
     <Compile Include="src\crypto\tls\TlsDHUtilities.cs" />
+    <Compile Include="src\crypto\tls\TlsDHVerifier.cs" />
     <Compile Include="src\crypto\tls\TlsDeflateCompression.cs" />
     <Compile Include="src\crypto\tls\TlsDheKeyExchange.cs" />
     <Compile Include="src\crypto\tls\TlsDsaSigner.cs" />
diff --git a/crypto/BouncyCastle.csproj b/crypto/BouncyCastle.csproj
index 981cefbe6..f772ed002 100644
--- a/crypto/BouncyCastle.csproj
+++ b/crypto/BouncyCastle.csproj
@@ -996,6 +996,7 @@
     <Compile Include="src\crypto\tls\DefaultTlsAgreementCredentials.cs" />
     <Compile Include="src\crypto\tls\DefaultTlsCipherFactory.cs" />
     <Compile Include="src\crypto\tls\DefaultTlsClient.cs" />
+    <Compile Include="src\crypto\tls\DefaultTlsDHVerifier.cs" />
     <Compile Include="src\crypto\tls\DefaultTlsEncryptionCredentials.cs" />
     <Compile Include="src\crypto\tls\DefaultTlsServer.cs" />
     <Compile Include="src\crypto\tls\DefaultTlsSignerCredentials.cs" />
@@ -1039,7 +1040,6 @@
     <Compile Include="src\crypto\tls\PskTlsServer.cs" />
     <Compile Include="src\crypto\tls\RecordStream.cs" />
     <Compile Include="src\crypto\tls\SecurityParameters.cs" />
-    <Compile Include="src\crypto\tls\ServerDHParams.cs" />
     <Compile Include="src\crypto\tls\ServerName.cs" />
     <Compile Include="src\crypto\tls\ServerNameList.cs" />
     <Compile Include="src\crypto\tls\ServerOnlyTlsAuthentication.cs" />
@@ -1070,6 +1070,7 @@
     <Compile Include="src\crypto\tls\TlsCredentials.cs" />
     <Compile Include="src\crypto\tls\TlsDHKeyExchange.cs" />
     <Compile Include="src\crypto\tls\TlsDHUtilities.cs" />
+    <Compile Include="src\crypto\tls\TlsDHVerifier.cs" />
     <Compile Include="src\crypto\tls\TlsDeflateCompression.cs" />
     <Compile Include="src\crypto\tls\TlsDheKeyExchange.cs" />
     <Compile Include="src\crypto\tls\TlsDsaSigner.cs" />
diff --git a/crypto/BouncyCastle.iOS.csproj b/crypto/BouncyCastle.iOS.csproj
index c97d9bf65..f9cebdc86 100644
--- a/crypto/BouncyCastle.iOS.csproj
+++ b/crypto/BouncyCastle.iOS.csproj
@@ -997,6 +997,7 @@
     <Compile Include="src\crypto\tls\DefaultTlsAgreementCredentials.cs" />
     <Compile Include="src\crypto\tls\DefaultTlsCipherFactory.cs" />
     <Compile Include="src\crypto\tls\DefaultTlsClient.cs" />
+    <Compile Include="src\crypto\tls\DefaultTlsDHVerifier.cs" />
     <Compile Include="src\crypto\tls\DefaultTlsEncryptionCredentials.cs" />
     <Compile Include="src\crypto\tls\DefaultTlsServer.cs" />
     <Compile Include="src\crypto\tls\DefaultTlsSignerCredentials.cs" />
@@ -1040,7 +1041,6 @@
     <Compile Include="src\crypto\tls\PskTlsServer.cs" />
     <Compile Include="src\crypto\tls\RecordStream.cs" />
     <Compile Include="src\crypto\tls\SecurityParameters.cs" />
-    <Compile Include="src\crypto\tls\ServerDHParams.cs" />
     <Compile Include="src\crypto\tls\ServerName.cs" />
     <Compile Include="src\crypto\tls\ServerNameList.cs" />
     <Compile Include="src\crypto\tls\ServerOnlyTlsAuthentication.cs" />
@@ -1071,6 +1071,7 @@
     <Compile Include="src\crypto\tls\TlsCredentials.cs" />
     <Compile Include="src\crypto\tls\TlsDHKeyExchange.cs" />
     <Compile Include="src\crypto\tls\TlsDHUtilities.cs" />
+    <Compile Include="src\crypto\tls\TlsDHVerifier.cs" />
     <Compile Include="src\crypto\tls\TlsDeflateCompression.cs" />
     <Compile Include="src\crypto\tls\TlsDheKeyExchange.cs" />
     <Compile Include="src\crypto\tls\TlsDsaSigner.cs" />
diff --git a/crypto/crypto.csproj b/crypto/crypto.csproj
index 7cd8de821..b6dfb3963 100644
--- a/crypto/crypto.csproj
+++ b/crypto/crypto.csproj
@@ -4869,6 +4869,11 @@
                     BuildAction = "Compile"
                 />
                 <File
+                    RelPath = "src\crypto\tls\DefaultTlsDHVerifier.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
                     RelPath = "src\crypto\tls\DefaultTlsEncryptionCredentials.cs"
                     SubType = "Code"
                     BuildAction = "Compile"
@@ -5084,11 +5089,6 @@
                     BuildAction = "Compile"
                 />
                 <File
-                    RelPath = "src\crypto\tls\ServerDHParams.cs"
-                    SubType = "Code"
-                    BuildAction = "Compile"
-                />
-                <File
                     RelPath = "src\crypto\tls\ServerSrpParams.cs"
                     SubType = "Code"
                     BuildAction = "Compile"
@@ -5249,6 +5249,11 @@
                     BuildAction = "Compile"
                 />
                 <File
+                    RelPath = "src\crypto\tls\TlsDHVerifier.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
                     RelPath = "src\crypto\tls\TlsDsaSigner.cs"
                     SubType = "Code"
                     BuildAction = "Compile"
diff --git a/crypto/src/crypto/tls/DefaultTlsClient.cs b/crypto/src/crypto/tls/DefaultTlsClient.cs
index 32a86e503..154a2c94b 100644
--- a/crypto/src/crypto/tls/DefaultTlsClient.cs
+++ b/crypto/src/crypto/tls/DefaultTlsClient.cs
@@ -14,14 +14,22 @@ namespace Org.BouncyCastle.Crypto.Tls
     public abstract class DefaultTlsClient
         :   AbstractTlsClient
     {
+        protected TlsDHVerifier mDHVerifier;
+
         public DefaultTlsClient()
-            :   base()
+            : this(new DefaultTlsCipherFactory())
         {
         }
 
         public DefaultTlsClient(TlsCipherFactory cipherFactory)
-            :   base(cipherFactory)
+            : this(cipherFactory, new DefaultTlsDHVerifier())
+        {
+        }
+
+        public DefaultTlsClient(TlsCipherFactory cipherFactory, TlsDHVerifier dhVerifier)
+            : base(cipherFactory)
         {
+            this.mDHVerifier = dhVerifier;
         }
 
         public override int[] GetCipherSuites()
@@ -85,12 +93,12 @@ namespace Org.BouncyCastle.Crypto.Tls
 
         protected virtual TlsKeyExchange CreateDHKeyExchange(int keyExchange)
         {
-            return new TlsDHKeyExchange(keyExchange, mSupportedSignatureAlgorithms, null);
+            return new TlsDHKeyExchange(keyExchange, mSupportedSignatureAlgorithms, mDHVerifier, null);
         }
 
         protected virtual TlsKeyExchange CreateDheKeyExchange(int keyExchange)
         {
-            return new TlsDheKeyExchange(keyExchange, mSupportedSignatureAlgorithms, null);
+            return new TlsDheKeyExchange(keyExchange, mSupportedSignatureAlgorithms, mDHVerifier, null);
         }
 
         protected virtual TlsKeyExchange CreateECDHKeyExchange(int keyExchange)
diff --git a/crypto/src/crypto/tls/DefaultTlsDHVerifier.cs b/crypto/src/crypto/tls/DefaultTlsDHVerifier.cs
new file mode 100644
index 000000000..ae26d04c3
--- /dev/null
+++ b/crypto/src/crypto/tls/DefaultTlsDHVerifier.cs
@@ -0,0 +1,101 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Crypto.Agreement;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    public class DefaultTlsDHVerifier
+        : TlsDHVerifier
+    {
+        public static readonly int DefaultMinimumPrimeBits = 2048;
+
+        protected static readonly IList DefaultGroups = Platform.CreateArrayList();
+
+        private static void AddDefaultGroup(DHParameters dhParameters)
+        {
+            DefaultGroups.Add(dhParameters);
+        }
+
+        static DefaultTlsDHVerifier()
+        {
+            AddDefaultGroup(DHStandardGroups.rfc7919_ffdhe2048);
+            AddDefaultGroup(DHStandardGroups.rfc7919_ffdhe3072);
+            AddDefaultGroup(DHStandardGroups.rfc7919_ffdhe4096);
+            AddDefaultGroup(DHStandardGroups.rfc7919_ffdhe6144);
+            AddDefaultGroup(DHStandardGroups.rfc7919_ffdhe8192);
+
+            AddDefaultGroup(DHStandardGroups.rfc3526_1536);
+            AddDefaultGroup(DHStandardGroups.rfc3526_2048);
+            AddDefaultGroup(DHStandardGroups.rfc3526_3072);
+            AddDefaultGroup(DHStandardGroups.rfc3526_4096);
+            AddDefaultGroup(DHStandardGroups.rfc3526_6144);
+            AddDefaultGroup(DHStandardGroups.rfc3526_8192);
+        }
+
+        // IList is (DHParameters)
+        protected readonly IList mGroups;
+        protected readonly int mMinimumPrimeBits;
+
+        /// <summary>Accept various standard DH groups with 'P' at least <c>DefaultMinimumPrimeBits</c> bits.</summary>
+        public DefaultTlsDHVerifier()
+            : this(DefaultMinimumPrimeBits)
+        {
+        }
+
+        /// <summary>Accept various standard DH groups with 'P' at least the specified number of bits.</summary>
+        public DefaultTlsDHVerifier(int minimumPrimeBits)
+            : this(DefaultGroups, minimumPrimeBits)
+        {
+        }
+
+        /// <summary>Accept a custom set of group parameters, subject to a minimum bitlength for 'P'.</summary>
+        /// <param name="groups">An <c>IList</c> of acceptable <c>DHParameters</c>.</param>
+        /// <param name="minimumPrimeBits">The minimum acceptable bitlength of the 'P' parameter.</param>
+        public DefaultTlsDHVerifier(IList groups, int minimumPrimeBits)
+        {
+            this.mGroups = groups;
+            this.mMinimumPrimeBits = minimumPrimeBits;
+        }
+
+        public virtual bool Accept(DHParameters dhParameters)
+        {
+            return CheckMinimumPrimeBits(dhParameters) && CheckGroup(dhParameters);
+        }
+
+        public virtual int MinimumPrimeBits
+        {
+            get { return mMinimumPrimeBits; }
+        }
+
+        protected virtual bool AreGroupsEqual(DHParameters a, DHParameters b)
+        {
+            return a == b || (AreParametersEqual(a.P, b.P) && AreParametersEqual(a.G, b.G));
+        }
+
+        protected virtual bool AreParametersEqual(BigInteger a, BigInteger b)
+        {
+            return a == b || a.Equals(b);
+        }
+
+        protected virtual bool CheckGroup(DHParameters dhParameters)
+        {
+            foreach (DHParameters group in mGroups)
+            {
+                if (AreGroupsEqual(dhParameters, group))
+                {
+                    return true;
+                }
+            }
+            return false;
+        }
+
+        protected virtual bool CheckMinimumPrimeBits(DHParameters dhParameters)
+        {
+            return dhParameters.P.BitLength >= MinimumPrimeBits;
+        }
+    }
+}
diff --git a/crypto/src/crypto/tls/DefaultTlsServer.cs b/crypto/src/crypto/tls/DefaultTlsServer.cs
index 97eaa079d..90f357687 100644
--- a/crypto/src/crypto/tls/DefaultTlsServer.cs
+++ b/crypto/src/crypto/tls/DefaultTlsServer.cs
@@ -138,12 +138,12 @@ namespace Org.BouncyCastle.Crypto.Tls
 
         protected virtual TlsKeyExchange CreateDHKeyExchange(int keyExchange)
         {
-            return new TlsDHKeyExchange(keyExchange, mSupportedSignatureAlgorithms, GetDHParameters());
+            return new TlsDHKeyExchange(keyExchange, mSupportedSignatureAlgorithms, null, GetDHParameters());
         }
 
         protected virtual TlsKeyExchange CreateDheKeyExchange(int keyExchange)
         {
-            return new TlsDheKeyExchange(keyExchange, mSupportedSignatureAlgorithms, GetDHParameters());
+            return new TlsDheKeyExchange(keyExchange, mSupportedSignatureAlgorithms, null, GetDHParameters());
         }
 
         protected virtual TlsKeyExchange CreateECDHKeyExchange(int keyExchange)
diff --git a/crypto/src/crypto/tls/PskTlsClient.cs b/crypto/src/crypto/tls/PskTlsClient.cs
index 2ef80dcfd..1dc119d7b 100644
--- a/crypto/src/crypto/tls/PskTlsClient.cs
+++ b/crypto/src/crypto/tls/PskTlsClient.cs
@@ -6,16 +6,23 @@ namespace Org.BouncyCastle.Crypto.Tls
     public class PskTlsClient
         :   AbstractTlsClient
     {
+        protected TlsDHVerifier mDHVerifier;
         protected TlsPskIdentity mPskIdentity;
 
         public PskTlsClient(TlsPskIdentity pskIdentity)
-            :   this(new DefaultTlsCipherFactory(), pskIdentity)
+            : this(new DefaultTlsCipherFactory(), pskIdentity)
         {
         }
 
         public PskTlsClient(TlsCipherFactory cipherFactory, TlsPskIdentity pskIdentity)
-            :   base(cipherFactory)
+            : this(cipherFactory, new DefaultTlsDHVerifier(), pskIdentity)
         {
+        }
+
+        public PskTlsClient(TlsCipherFactory cipherFactory, TlsDHVerifier dhVerifier, TlsPskIdentity pskIdentity)
+            : base(cipherFactory)
+        {
+            this.mDHVerifier = dhVerifier;
             this.mPskIdentity = pskIdentity;
         }
 
@@ -63,8 +70,8 @@ namespace Org.BouncyCastle.Crypto.Tls
 
         protected virtual TlsKeyExchange CreatePskKeyExchange(int keyExchange)
         {
-            return new TlsPskKeyExchange(keyExchange, mSupportedSignatureAlgorithms, mPskIdentity, null, null, mNamedCurves,
-                mClientECPointFormats, mServerECPointFormats);
+            return new TlsPskKeyExchange(keyExchange, mSupportedSignatureAlgorithms, mPskIdentity, null, mDHVerifier, null,
+                mNamedCurves, mClientECPointFormats, mServerECPointFormats);
         }
     }
 }
diff --git a/crypto/src/crypto/tls/PskTlsServer.cs b/crypto/src/crypto/tls/PskTlsServer.cs
index b0fb67c04..a3778420d 100644
--- a/crypto/src/crypto/tls/PskTlsServer.cs
+++ b/crypto/src/crypto/tls/PskTlsServer.cs
@@ -87,7 +87,7 @@ namespace Org.BouncyCastle.Crypto.Tls
         protected virtual TlsKeyExchange CreatePskKeyExchange(int keyExchange)
         {
             return new TlsPskKeyExchange(keyExchange, mSupportedSignatureAlgorithms, null, mPskIdentityManager,
-                GetDHParameters(), mNamedCurves, mClientECPointFormats, mServerECPointFormats);
+                null, GetDHParameters(), mNamedCurves, mClientECPointFormats, mServerECPointFormats);
         }
     }
 }
diff --git a/crypto/src/crypto/tls/ServerDHParams.cs b/crypto/src/crypto/tls/ServerDHParams.cs
deleted file mode 100644
index b09262771..000000000
--- a/crypto/src/crypto/tls/ServerDHParams.cs
+++ /dev/null
@@ -1,61 +0,0 @@
-using System;
-using System.IO;
-
-using Org.BouncyCastle.Crypto.Parameters;
-using Org.BouncyCastle.Math;
-
-namespace Org.BouncyCastle.Crypto.Tls
-{
-    public class ServerDHParams
-    {
-        protected readonly DHPublicKeyParameters mPublicKey;
-
-        public ServerDHParams(DHPublicKeyParameters publicKey)
-        {
-            if (publicKey == null)
-                throw new ArgumentNullException("publicKey");
-
-            this.mPublicKey = publicKey;
-        }
-
-        public virtual DHPublicKeyParameters PublicKey
-        {
-            get { return mPublicKey; }
-        }
-
-        /**
-         * Encode this {@link ServerDHParams} to a {@link Stream}.
-         * 
-         * @param output
-         *            the {@link Stream} to encode to.
-         * @throws IOException
-         */
-        public virtual void Encode(Stream output)
-        {
-            DHParameters dhParameters = mPublicKey.Parameters;
-            BigInteger Ys = mPublicKey.Y;
-
-            TlsDHUtilities.WriteDHParameter(dhParameters.P, output);
-            TlsDHUtilities.WriteDHParameter(dhParameters.G, output);
-            TlsDHUtilities.WriteDHParameter(Ys, output);
-        }
-
-        /**
-         * Parse a {@link ServerDHParams} from a {@link Stream}.
-         * 
-         * @param input
-         *            the {@link Stream} to parse from.
-         * @return a {@link ServerDHParams} object.
-         * @throws IOException
-         */
-        public static ServerDHParams Parse(Stream input)
-        {
-            BigInteger p = TlsDHUtilities.ReadDHParameter(input);
-            BigInteger g = TlsDHUtilities.ReadDHParameter(input);
-            BigInteger Ys = TlsDHUtilities.ReadDHParameter(input);
-
-            return new ServerDHParams(
-                TlsDHUtilities.ValidateDHPublicKey(new DHPublicKeyParameters(Ys, new DHParameters(p, g))));
-        }
-    }
-}
diff --git a/crypto/src/crypto/tls/TlsDHKeyExchange.cs b/crypto/src/crypto/tls/TlsDHKeyExchange.cs
index d179068bb..59d52265b 100644
--- a/crypto/src/crypto/tls/TlsDHKeyExchange.cs
+++ b/crypto/src/crypto/tls/TlsDHKeyExchange.cs
@@ -4,7 +4,6 @@ using System.IO;
 
 using Org.BouncyCastle.Asn1.X509;
 using Org.BouncyCastle.Crypto.Parameters;
-using Org.BouncyCastle.Math;
 using Org.BouncyCastle.Security;
 
 namespace Org.BouncyCastle.Crypto.Tls
@@ -14,6 +13,7 @@ namespace Org.BouncyCastle.Crypto.Tls
         :   AbstractTlsKeyExchange
     {
         protected TlsSigner mTlsSigner;
+        protected TlsDHVerifier mDHVerifier;
         protected DHParameters mDHParameters;
 
         protected AsymmetricKeyParameter mServerPublicKey;
@@ -22,7 +22,7 @@ namespace Org.BouncyCastle.Crypto.Tls
         protected DHPrivateKeyParameters mDHAgreePrivateKey;
         protected DHPublicKeyParameters mDHAgreePublicKey;
 
-        public TlsDHKeyExchange(int keyExchange, IList supportedSignatureAlgorithms, DHParameters dhParameters)
+        public TlsDHKeyExchange(int keyExchange, IList supportedSignatureAlgorithms, TlsDHVerifier dhVerifier, DHParameters dhParameters)
             :   base(keyExchange, supportedSignatureAlgorithms)
         {
             switch (keyExchange)
@@ -42,6 +42,7 @@ namespace Org.BouncyCastle.Crypto.Tls
                 throw new InvalidOperationException("unsupported key exchange algorithm");
             }
 
+            this.mDHVerifier = dhVerifier;
             this.mDHParameters = dhParameters;
         }
 
@@ -84,8 +85,8 @@ namespace Org.BouncyCastle.Crypto.Tls
             {
                 try
                 {
-                    this.mDHAgreePublicKey = TlsDHUtilities.ValidateDHPublicKey((DHPublicKeyParameters)this.mServerPublicKey);
-                    this.mDHParameters = ValidateDHParameters(mDHAgreePublicKey.Parameters);
+                    this.mDHAgreePublicKey = (DHPublicKeyParameters)this.mServerPublicKey;
+                    this.mDHParameters = mDHAgreePublicKey.Parameters;
                 }
                 catch (InvalidCastException e)
                 {
@@ -143,10 +144,8 @@ namespace Org.BouncyCastle.Crypto.Tls
 
             // DH_anon is handled here, DHE_* in a subclass
 
-            ServerDHParams dhParams = ServerDHParams.Parse(input);
-
-            this.mDHAgreePublicKey = TlsDHUtilities.ValidateDHPublicKey(dhParams.PublicKey);
-            this.mDHParameters = ValidateDHParameters(mDHAgreePublicKey.Parameters);
+            this.mDHParameters = TlsDHUtilities.ReceiveDHParameters(mDHVerifier, input);
+            this.mDHAgreePublicKey = new DHPublicKeyParameters(TlsDHUtilities.ReadDHParameter(input), mDHParameters);
         }
 
         public override void ValidateCertificateRequest(CertificateRequest certificateRequest)
@@ -223,9 +222,7 @@ namespace Org.BouncyCastle.Crypto.Tls
                 return;
             }
 
-            BigInteger Yc = TlsDHUtilities.ReadDHParameter(input);
-
-            this.mDHAgreePublicKey = TlsDHUtilities.ValidateDHPublicKey(new DHPublicKeyParameters(Yc, mDHParameters));
+            this.mDHAgreePublicKey = new DHPublicKeyParameters(TlsDHUtilities.ReadDHParameter(input), mDHParameters);
         }
 
         public override byte[] GeneratePremasterSecret()
@@ -242,18 +239,5 @@ namespace Org.BouncyCastle.Crypto.Tls
 
             throw new TlsFatalAlert(AlertDescription.internal_error);
         }
-
-        protected virtual int MinimumPrimeBits
-        {
-            get { return 1024; }
-        }
-
-        protected virtual DHParameters ValidateDHParameters(DHParameters parameters)
-        {
-            if (parameters.P.BitLength < MinimumPrimeBits)
-                throw new TlsFatalAlert(AlertDescription.insufficient_security);
-
-            return TlsDHUtilities.ValidateDHParameters(parameters);
-        }
     }
 }
diff --git a/crypto/src/crypto/tls/TlsDHUtilities.cs b/crypto/src/crypto/tls/TlsDHUtilities.cs
index 6df61cbed..9567ee062 100644
--- a/crypto/src/crypto/tls/TlsDHUtilities.cs
+++ b/crypto/src/crypto/tls/TlsDHUtilities.cs
@@ -417,46 +417,43 @@ namespace Org.BouncyCastle.Crypto.Tls
             AsymmetricCipherKeyPair kp = GenerateDHKeyPair(random, dhParams);
 
             DHPublicKeyParameters dhPublic = (DHPublicKeyParameters)kp.Public;
-            new ServerDHParams(dhPublic).Encode(output);
+            WriteDHParameters(dhParams, output);
+            WriteDHParameter(dhPublic.Y, output);
 
             return (DHPrivateKeyParameters)kp.Private;
         }
 
-        public static DHParameters ValidateDHParameters(DHParameters parameters)
+        public static BigInteger ReadDHParameter(Stream input)
         {
-            BigInteger p = parameters.P;
-            BigInteger g = parameters.G;
-
-            if (!p.IsProbablePrime(2))
-                throw new TlsFatalAlert(AlertDescription.illegal_parameter);
-            if (g.CompareTo(Two) < 0 || g.CompareTo(p.Subtract(Two)) > 0)
-                throw new TlsFatalAlert(AlertDescription.illegal_parameter);
-
-
-            return parameters;
+            return new BigInteger(1, TlsUtilities.ReadOpaque16(input));
         }
 
-        public static DHPublicKeyParameters ValidateDHPublicKey(DHPublicKeyParameters key)
+        public static DHParameters ReadDHParameters(Stream input)
         {
-            DHParameters parameters = ValidateDHParameters(key.Parameters);
-
-            BigInteger Y = key.Y;
-            if (Y.CompareTo(Two) < 0 || Y.CompareTo(parameters.P.Subtract(Two)) > 0)
-                throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+            BigInteger p = ReadDHParameter(input);
+            BigInteger g = ReadDHParameter(input);
 
-            // TODO See RFC 2631 for more discussion of Diffie-Hellman validation
-
-            return key;
+            return new DHParameters(p, g);
         }
 
-        public static BigInteger ReadDHParameter(Stream input)
+        public static DHParameters ReceiveDHParameters(TlsDHVerifier dhVerifier, Stream input)
         {
-            return new BigInteger(1, TlsUtilities.ReadOpaque16(input));
+            DHParameters dhParameters = ReadDHParameters(input);
+            if (!dhVerifier.Accept(dhParameters))
+                throw new TlsFatalAlert(AlertDescription.insufficient_security);
+
+            return dhParameters;
         }
 
         public static void WriteDHParameter(BigInteger x, Stream output)
         {
             TlsUtilities.WriteOpaque16(BigIntegers.AsUnsignedByteArray(x), output);
         }
+
+        public static void WriteDHParameters(DHParameters dhParameters, Stream output)
+        {
+            WriteDHParameter(dhParameters.P, output);
+            WriteDHParameter(dhParameters.G, output);
+        }
     }
 }
diff --git a/crypto/src/crypto/tls/TlsDHVerifier.cs b/crypto/src/crypto/tls/TlsDHVerifier.cs
new file mode 100644
index 000000000..867403c3c
--- /dev/null
+++ b/crypto/src/crypto/tls/TlsDHVerifier.cs
@@ -0,0 +1,15 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Parameters;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    /// <summary>An interface for verifying that Diffie-Hellman parameters are acceptable.</summary>
+    public interface TlsDHVerifier
+    {
+        /// <summary>Verify that the given <c>DHParameters</c> are acceptable.</summary>
+        /// <param name="dhParameters">The <c>DHParameters</c> to verify.</param>
+        /// <returns>true if (and only if) the specified parameters are acceptable.</returns>
+        bool Accept(DHParameters dhParameters);
+    }
+}
diff --git a/crypto/src/crypto/tls/TlsDheKeyExchange.cs b/crypto/src/crypto/tls/TlsDheKeyExchange.cs
index cdd629247..402c74720 100644
--- a/crypto/src/crypto/tls/TlsDheKeyExchange.cs
+++ b/crypto/src/crypto/tls/TlsDheKeyExchange.cs
@@ -3,7 +3,6 @@ using System.Collections;
 using System.IO;
 
 using Org.BouncyCastle.Crypto.Parameters;
-using Org.BouncyCastle.Math;
 using Org.BouncyCastle.Security;
 using Org.BouncyCastle.Utilities.IO;
 
@@ -14,8 +13,8 @@ namespace Org.BouncyCastle.Crypto.Tls
     {
         protected TlsSignerCredentials mServerCredentials = null;
 
-        public TlsDheKeyExchange(int keyExchange, IList supportedSignatureAlgorithms, DHParameters dhParameters)
-            :   base(keyExchange, supportedSignatureAlgorithms, dhParameters)
+        public TlsDheKeyExchange(int keyExchange, IList supportedSignatureAlgorithms, TlsDHVerifier dhVerifier, DHParameters dhParameters)
+            :   base(keyExchange, supportedSignatureAlgorithms, dhVerifier, dhParameters)
         {
         }
 
@@ -69,7 +68,8 @@ namespace Org.BouncyCastle.Crypto.Tls
             SignerInputBuffer buf = new SignerInputBuffer();
             Stream teeIn = new TeeInputStream(input, buf);
 
-            ServerDHParams dhParams = ServerDHParams.Parse(teeIn);
+            this.mDHParameters = TlsDHUtilities.ReceiveDHParameters(mDHVerifier, teeIn);
+            this.mDHAgreePublicKey = new DHPublicKeyParameters(TlsDHUtilities.ReadDHParameter(teeIn), mDHParameters);
 
             DigitallySigned signed_params = ParseSignature(input);
 
@@ -77,9 +77,6 @@ namespace Org.BouncyCastle.Crypto.Tls
             buf.UpdateSigner(signer);
             if (!signer.VerifySignature(signed_params.Signature))
                 throw new TlsFatalAlert(AlertDescription.decrypt_error);
-
-            this.mDHAgreePublicKey = TlsDHUtilities.ValidateDHPublicKey(dhParams.PublicKey);
-            this.mDHParameters = ValidateDHParameters(mDHAgreePublicKey.Parameters);
         }
 
         protected virtual ISigner InitVerifyer(TlsSigner tlsSigner, SignatureAndHashAlgorithm algorithm,
diff --git a/crypto/src/crypto/tls/TlsPskKeyExchange.cs b/crypto/src/crypto/tls/TlsPskKeyExchange.cs
index 0af7f7a69..36ef09e85 100644
--- a/crypto/src/crypto/tls/TlsPskKeyExchange.cs
+++ b/crypto/src/crypto/tls/TlsPskKeyExchange.cs
@@ -4,7 +4,6 @@ using System.IO;
 
 using Org.BouncyCastle.Asn1.X509;
 using Org.BouncyCastle.Crypto.Parameters;
-using Org.BouncyCastle.Math;
 using Org.BouncyCastle.Security;
 using Org.BouncyCastle.Utilities;
 using Org.BouncyCastle.Utilities.IO;
@@ -18,6 +17,7 @@ namespace Org.BouncyCastle.Crypto.Tls
         protected TlsPskIdentity mPskIdentity;
         protected TlsPskIdentityManager mPskIdentityManager;
 
+        protected TlsDHVerifier mDHVerifier;
         protected DHParameters mDHParameters;
         protected int[] mNamedCurves;
         protected byte[] mClientECPointFormats, mServerECPointFormats;
@@ -37,7 +37,7 @@ namespace Org.BouncyCastle.Crypto.Tls
         protected byte[] mPremasterSecret;
 
         public TlsPskKeyExchange(int keyExchange, IList supportedSignatureAlgorithms, TlsPskIdentity pskIdentity,
-            TlsPskIdentityManager pskIdentityManager, DHParameters dhParameters, int[] namedCurves,
+            TlsPskIdentityManager pskIdentityManager, TlsDHVerifier dhVerifier, DHParameters dhParameters, int[] namedCurves,
             byte[] clientECPointFormats, byte[] serverECPointFormats)
             :   base(keyExchange, supportedSignatureAlgorithms)
         {
@@ -54,6 +54,7 @@ namespace Org.BouncyCastle.Crypto.Tls
 
             this.mPskIdentity = pskIdentity;
             this.mPskIdentityManager = pskIdentityManager;
+            this.mDHVerifier = dhVerifier;
             this.mDHParameters = dhParameters;
             this.mNamedCurves = namedCurves;
             this.mClientECPointFormats = clientECPointFormats;
@@ -162,10 +163,8 @@ namespace Org.BouncyCastle.Crypto.Tls
 
             if (this.mKeyExchange == KeyExchangeAlgorithm.DHE_PSK)
             {
-                ServerDHParams serverDHParams = ServerDHParams.Parse(input);
-
-                this.mDHAgreePublicKey = TlsDHUtilities.ValidateDHPublicKey(serverDHParams.PublicKey);
-                this.mDHParameters = mDHAgreePublicKey.Parameters;
+                this.mDHParameters = TlsDHUtilities.ReceiveDHParameters(mDHVerifier, input);
+                this.mDHAgreePublicKey = new DHPublicKeyParameters(TlsDHUtilities.ReadDHParameter(input), mDHParameters);
             }
             else if (this.mKeyExchange == KeyExchangeAlgorithm.ECDHE_PSK)
             {
@@ -240,9 +239,7 @@ namespace Org.BouncyCastle.Crypto.Tls
 
             if (this.mKeyExchange == KeyExchangeAlgorithm.DHE_PSK)
             {
-                BigInteger Yc = TlsDHUtilities.ReadDHParameter(input);
-
-                this.mDHAgreePublicKey = TlsDHUtilities.ValidateDHPublicKey(new DHPublicKeyParameters(Yc, mDHParameters));
+                this.mDHAgreePublicKey = new DHPublicKeyParameters(TlsDHUtilities.ReadDHParameter(input), mDHParameters);
             }
             else if (this.mKeyExchange == KeyExchangeAlgorithm.ECDHE_PSK)
             {