summary refs log tree commit diff
diff options
context:
space:
mode:
authorPeter Dettman <peter.dettman@bouncycastle.org>2015-03-09 13:55:26 +0700
committerPeter Dettman <peter.dettman@bouncycastle.org>2015-03-09 13:55:26 +0700
commite772fefc00c6d2649ebf1be0c6b48bd78ebbb427 (patch)
treef43ff32bb1544d68af4d23c7da38661299fa14ba
parentPorting from Java build (diff)
downloadBouncyCastle.NET-ed25519-e772fefc00c6d2649ebf1be0c6b48bd78ebbb427.tar.xz
Refactor TLS ciphersuite processing
-rw-r--r--crypto/src/crypto/tls/AbstractTlsClient.cs8
-rw-r--r--crypto/src/crypto/tls/AbstractTlsServer.cs8
-rw-r--r--crypto/src/crypto/tls/DefaultTlsClient.cs399
-rw-r--r--crypto/src/crypto/tls/DefaultTlsServer.cs556
-rw-r--r--crypto/src/crypto/tls/PskTlsClient.cs216
-rw-r--r--crypto/src/crypto/tls/PskTlsServer.cs308
-rw-r--r--crypto/src/crypto/tls/SrpTlsClient.cs51
-rw-r--r--crypto/src/crypto/tls/SrpTlsServer.cs77
-rw-r--r--crypto/src/crypto/tls/TlsUtilities.cs522
9 files changed, 652 insertions, 1493 deletions
diff --git a/crypto/src/crypto/tls/AbstractTlsClient.cs b/crypto/src/crypto/tls/AbstractTlsClient.cs
index 569979288..046feb78c 100644
--- a/crypto/src/crypto/tls/AbstractTlsClient.cs
+++ b/crypto/src/crypto/tls/AbstractTlsClient.cs
@@ -243,6 +243,14 @@ namespace Org.BouncyCastle.Crypto.Tls
             }
         }
 
+        public override TlsCipher GetCipher()
+        {
+            int encryptionAlgorithm = TlsUtilities.GetEncryptionAlgorithm(mSelectedCipherSuite);
+            int macAlgorithm = TlsUtilities.GetMacAlgorithm(mSelectedCipherSuite);
+
+            return mCipherFactory.CreateCipher(mContext, encryptionAlgorithm, macAlgorithm);
+        }
+
         public virtual void NotifyNewSessionTicket(NewSessionTicket newSessionTicket)
         {
         }
diff --git a/crypto/src/crypto/tls/AbstractTlsServer.cs b/crypto/src/crypto/tls/AbstractTlsServer.cs
index b0a5f0d52..7fe3fcbe5 100644
--- a/crypto/src/crypto/tls/AbstractTlsServer.cs
+++ b/crypto/src/crypto/tls/AbstractTlsServer.cs
@@ -320,6 +320,14 @@ namespace Org.BouncyCastle.Crypto.Tls
             }
         }
 
+        public override TlsCipher GetCipher()
+        {
+            int encryptionAlgorithm = TlsUtilities.GetEncryptionAlgorithm(mSelectedCipherSuite);
+            int macAlgorithm = TlsUtilities.GetMacAlgorithm(mSelectedCipherSuite);
+
+            return mCipherFactory.CreateCipher(mContext, encryptionAlgorithm, macAlgorithm);
+        }
+
         public virtual NewSessionTicket GetNewSessionTicket()
         {
             /*
diff --git a/crypto/src/crypto/tls/DefaultTlsClient.cs b/crypto/src/crypto/tls/DefaultTlsClient.cs
index f07080cbd..ff7e6da85 100644
--- a/crypto/src/crypto/tls/DefaultTlsClient.cs
+++ b/crypto/src/crypto/tls/DefaultTlsClient.cs
@@ -48,395 +48,28 @@ namespace Org.BouncyCastle.Crypto.Tls
 
         public override TlsKeyExchange GetKeyExchange()
         {
-            switch (mSelectedCipherSuite)
-            {
-            case CipherSuite.TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA:
-            case CipherSuite.TLS_DH_DSS_WITH_AES_128_CBC_SHA:
-            case CipherSuite.TLS_DH_DSS_WITH_AES_128_CBC_SHA256:
-            case CipherSuite.TLS_DH_DSS_WITH_AES_128_GCM_SHA256:
-            case CipherSuite.TLS_DH_DSS_WITH_AES_256_CBC_SHA:
-            case CipherSuite.TLS_DH_DSS_WITH_AES_256_CBC_SHA256:
-            case CipherSuite.TLS_DH_DSS_WITH_AES_256_GCM_SHA384:
-            case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA:
-            case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256:
-            case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256:
-            case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA:
-            case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256:
-            case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384:
-            case CipherSuite.TLS_DH_DSS_WITH_SEED_CBC_SHA:
-                return CreateDHKeyExchange(KeyExchangeAlgorithm.DH_DSS);
-
-            case CipherSuite.TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA:
-            case CipherSuite.TLS_DH_RSA_WITH_AES_128_CBC_SHA:
-            case CipherSuite.TLS_DH_RSA_WITH_AES_128_CBC_SHA256:
-            case CipherSuite.TLS_DH_RSA_WITH_AES_128_GCM_SHA256:
-            case CipherSuite.TLS_DH_RSA_WITH_AES_256_CBC_SHA:
-            case CipherSuite.TLS_DH_RSA_WITH_AES_256_CBC_SHA256:
-            case CipherSuite.TLS_DH_RSA_WITH_AES_256_GCM_SHA384:
-            case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA:
-            case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256:
-            case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256:
-            case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA:
-            case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256:
-            case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384:
-            case CipherSuite.TLS_DH_RSA_WITH_SEED_CBC_SHA:
-                return CreateDHKeyExchange(KeyExchangeAlgorithm.DH_RSA);
-
-            case CipherSuite.TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA:
-            case CipherSuite.TLS_DHE_DSS_WITH_AES_128_CBC_SHA:
-            case CipherSuite.TLS_DHE_DSS_WITH_AES_128_CBC_SHA256:
-            case CipherSuite.TLS_DHE_DSS_WITH_AES_128_GCM_SHA256:
-            case CipherSuite.TLS_DHE_DSS_WITH_AES_256_CBC_SHA:
-            case CipherSuite.TLS_DHE_DSS_WITH_AES_256_CBC_SHA256:
-            case CipherSuite.TLS_DHE_DSS_WITH_AES_256_GCM_SHA384:
-            case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA:
-            case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256:
-            case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256:
-            case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA:
-            case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256:
-            case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384:
-            case CipherSuite.TLS_DHE_DSS_WITH_SEED_CBC_SHA:
-                return CreateDheKeyExchange(KeyExchangeAlgorithm.DHE_DSS);
-
-            case CipherSuite.TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA:
-            case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA:
-            case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA256:
-            case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CCM:
-            case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CCM_8:
-            case CipherSuite.TLS_DHE_RSA_WITH_AES_128_GCM_SHA256:
-            case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA:
-            case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA256:
-            case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CCM:
-            case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CCM_8:
-            case CipherSuite.TLS_DHE_RSA_WITH_AES_256_GCM_SHA384:
-            case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA:
-            case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256:
-            case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256:
-            case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA:
-            case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256:
-            case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384:
-            case CipherSuite.TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256:
-            case CipherSuite.TLS_DHE_RSA_WITH_ESTREAM_SALSA20_SHA1:
-            case CipherSuite.TLS_DHE_RSA_WITH_SALSA20_SHA1:
-            case CipherSuite.TLS_DHE_RSA_WITH_SEED_CBC_SHA:
-                return CreateDheKeyExchange(KeyExchangeAlgorithm.DHE_RSA);
-
-            case CipherSuite.TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA:
-            case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA:
-            case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256:
-            case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256:
-            case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA:
-            case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384:
-            case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384:
-            case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256:
-            case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256:
-            case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384:
-            case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384:
-            case CipherSuite.TLS_ECDH_ECDSA_WITH_NULL_SHA:
-            case CipherSuite.TLS_ECDH_ECDSA_WITH_RC4_128_SHA:
-                return CreateECDHKeyExchange(KeyExchangeAlgorithm.ECDH_ECDSA);
-
-            case CipherSuite.TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA:
-            case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_CBC_SHA:
-            case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256:
-            case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256:
-            case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_CBC_SHA:
-            case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384:
-            case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384:
-            case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256:
-            case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256:
-            case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384:
-            case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384:
-            case CipherSuite.TLS_ECDH_RSA_WITH_NULL_SHA:
-            case CipherSuite.TLS_ECDH_RSA_WITH_RC4_128_SHA:
-                return CreateECDHKeyExchange(KeyExchangeAlgorithm.ECDH_RSA);
+            int keyExchangeAlgorithm = TlsUtilities.GetKeyExchangeAlgorithm(mSelectedCipherSuite);
 
-            case CipherSuite.TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA:
-            case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA:
-            case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256:
-            case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CCM:
-            case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8:
-            case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256:
-            case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA:
-            case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384:
-            case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CCM:
-            case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8:
-            case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384:
-            case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256:
-            case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256:
-            case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384:
-            case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384:
-            case CipherSuite.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256:
-            case CipherSuite.TLS_ECDHE_ECDSA_WITH_ESTREAM_SALSA20_SHA1:
-            case CipherSuite.TLS_ECDHE_ECDSA_WITH_NULL_SHA:
-            case CipherSuite.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA:
-            case CipherSuite.TLS_ECDHE_ECDSA_WITH_SALSA20_SHA1:
-                return CreateECDheKeyExchange(KeyExchangeAlgorithm.ECDHE_ECDSA);
-
-            case CipherSuite.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA:
-            case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA:
-            case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256:
-            case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256:
-            case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA:
-            case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384:
-            case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384:
-            case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256:
-            case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256:
-            case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384:
-            case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384:
-            case CipherSuite.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256:
-            case CipherSuite.TLS_ECDHE_RSA_WITH_ESTREAM_SALSA20_SHA1:
-            case CipherSuite.TLS_ECDHE_RSA_WITH_NULL_SHA:
-            case CipherSuite.TLS_ECDHE_RSA_WITH_RC4_128_SHA:
-            case CipherSuite.TLS_ECDHE_RSA_WITH_SALSA20_SHA1:
-                return CreateECDheKeyExchange(KeyExchangeAlgorithm.ECDHE_RSA);
-
-            case CipherSuite.TLS_RSA_WITH_3DES_EDE_CBC_SHA:
-            case CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA:
-            case CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA256:
-            case CipherSuite.TLS_RSA_WITH_AES_128_CCM:
-            case CipherSuite.TLS_RSA_WITH_AES_128_CCM_8:
-            case CipherSuite.TLS_RSA_WITH_AES_128_GCM_SHA256:
-            case CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA:
-            case CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA256:
-            case CipherSuite.TLS_RSA_WITH_AES_256_CCM:
-            case CipherSuite.TLS_RSA_WITH_AES_256_CCM_8:
-            case CipherSuite.TLS_RSA_WITH_AES_256_GCM_SHA384:
-            case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_CBC_SHA:
-            case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256:
-            case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256:
-            case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_CBC_SHA:
-            case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256:
-            case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384:
-            case CipherSuite.TLS_RSA_WITH_ESTREAM_SALSA20_SHA1:
-            case CipherSuite.TLS_RSA_WITH_NULL_MD5:
-            case CipherSuite.TLS_RSA_WITH_NULL_SHA:
-            case CipherSuite.TLS_RSA_WITH_NULL_SHA256:
-            case CipherSuite.TLS_RSA_WITH_RC4_128_MD5:
-            case CipherSuite.TLS_RSA_WITH_RC4_128_SHA:
-            case CipherSuite.TLS_RSA_WITH_SALSA20_SHA1:
-            case CipherSuite.TLS_RSA_WITH_SEED_CBC_SHA:
-                return CreateRsaKeyExchange();
-
-            default:
-                /*
-                    * Note: internal error here; the TlsProtocol implementation verifies that the
-                    * server-selected cipher suite was in the list of client-offered cipher suites, so if
-                    * we now can't produce an implementation, we shouldn't have offered it!
-                    */
-                throw new TlsFatalAlert(AlertDescription.internal_error);
-            }
-        }
-
-        public override TlsCipher GetCipher()
-        {
-            switch (mSelectedCipherSuite)
+            switch (keyExchangeAlgorithm)
             {
-            case CipherSuite.TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA:
-            case CipherSuite.TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA:
-            case CipherSuite.TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA:
-            case CipherSuite.TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA:
-            case CipherSuite.TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA:
-            case CipherSuite.TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA:
-            case CipherSuite.TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA:
-            case CipherSuite.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA:
-            case CipherSuite.TLS_RSA_WITH_3DES_EDE_CBC_SHA:
-                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.cls_3DES_EDE_CBC, MacAlgorithm.hmac_sha1);
-
-            case CipherSuite.TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256:
-            case CipherSuite.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256:
-            case CipherSuite.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256:
-                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AEAD_CHACHA20_POLY1305, MacAlgorithm.cls_null);
-
-            case CipherSuite.TLS_DH_DSS_WITH_AES_128_CBC_SHA:
-            case CipherSuite.TLS_DH_RSA_WITH_AES_128_CBC_SHA:
-            case CipherSuite.TLS_DHE_DSS_WITH_AES_128_CBC_SHA:
-            case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA:
-            case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA:
-            case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_CBC_SHA:
-            case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA:
-            case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA:
-            case CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA:
-                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_128_CBC, MacAlgorithm.hmac_sha1);
+            case KeyExchangeAlgorithm.DH_DSS:
+            case KeyExchangeAlgorithm.DH_RSA:
+                return CreateDHKeyExchange(keyExchangeAlgorithm);
 
-            case CipherSuite.TLS_DH_DSS_WITH_AES_128_CBC_SHA256:
-            case CipherSuite.TLS_DH_RSA_WITH_AES_128_CBC_SHA256:
-            case CipherSuite.TLS_DHE_DSS_WITH_AES_128_CBC_SHA256:
-            case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA256:
-            case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256:
-            case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256:
-            case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256:
-            case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256:
-            case CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA256:
-                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_128_CBC, MacAlgorithm.hmac_sha256);
+            case KeyExchangeAlgorithm.DHE_DSS:
+            case KeyExchangeAlgorithm.DHE_RSA:
+                return CreateDheKeyExchange(keyExchangeAlgorithm);
 
-            case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CCM:
-            case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CCM:
-            case CipherSuite.TLS_RSA_WITH_AES_128_CCM:
-                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_128_CCM, MacAlgorithm.cls_null);
+            case KeyExchangeAlgorithm.ECDH_ECDSA:
+            case KeyExchangeAlgorithm.ECDH_RSA:
+                return CreateECDHKeyExchange(keyExchangeAlgorithm);
 
-            case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CCM_8:
-            case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8:
-            case CipherSuite.TLS_RSA_WITH_AES_128_CCM_8:
-                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_128_CCM_8, MacAlgorithm.cls_null);
+            case KeyExchangeAlgorithm.ECDHE_ECDSA:
+            case KeyExchangeAlgorithm.ECDHE_RSA:
+                return CreateECDheKeyExchange(keyExchangeAlgorithm);
 
-            case CipherSuite.TLS_DH_DSS_WITH_AES_128_GCM_SHA256:
-            case CipherSuite.TLS_DH_RSA_WITH_AES_128_GCM_SHA256:
-            case CipherSuite.TLS_DHE_DSS_WITH_AES_128_GCM_SHA256:
-            case CipherSuite.TLS_DHE_RSA_WITH_AES_128_GCM_SHA256:
-            case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256:
-            case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256:
-            case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256:
-            case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256:
-            case CipherSuite.TLS_RSA_WITH_AES_128_GCM_SHA256:
-                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_128_GCM, MacAlgorithm.cls_null);
-
-            case CipherSuite.TLS_DH_DSS_WITH_AES_256_CBC_SHA:
-            case CipherSuite.TLS_DH_RSA_WITH_AES_256_CBC_SHA:
-            case CipherSuite.TLS_DHE_DSS_WITH_AES_256_CBC_SHA:
-            case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA:
-            case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA:
-            case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_CBC_SHA:
-            case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA:
-            case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA:
-            case CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA:
-                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_256_CBC, MacAlgorithm.hmac_sha1);
-
-            case CipherSuite.TLS_DH_DSS_WITH_AES_256_CBC_SHA256:
-            case CipherSuite.TLS_DH_RSA_WITH_AES_256_CBC_SHA256:
-            case CipherSuite.TLS_DHE_DSS_WITH_AES_256_CBC_SHA256:
-            case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA256:
-            case CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA256:
-                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_256_CBC, MacAlgorithm.hmac_sha256);
-
-            case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384:
-            case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384:
-            case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384:
-            case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384:
-                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_256_CBC, MacAlgorithm.hmac_sha384);
-
-            case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CCM:
-            case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CCM:
-            case CipherSuite.TLS_RSA_WITH_AES_256_CCM:
-                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_256_CCM, MacAlgorithm.cls_null);
-
-            case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CCM_8:
-            case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8:
-            case CipherSuite.TLS_RSA_WITH_AES_256_CCM_8:
-                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_256_CCM_8, MacAlgorithm.cls_null);
-
-            case CipherSuite.TLS_DH_DSS_WITH_AES_256_GCM_SHA384:
-            case CipherSuite.TLS_DH_RSA_WITH_AES_256_GCM_SHA384:
-            case CipherSuite.TLS_DHE_DSS_WITH_AES_256_GCM_SHA384:
-            case CipherSuite.TLS_DHE_RSA_WITH_AES_256_GCM_SHA384:
-            case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384:
-            case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384:
-            case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384:
-            case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384:
-            case CipherSuite.TLS_RSA_WITH_AES_256_GCM_SHA384:
-                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_256_GCM, MacAlgorithm.cls_null);
-
-            case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA:
-            case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA:
-            case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA:
-            case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA:
-            case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_CBC_SHA:
-                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.CAMELLIA_128_CBC, MacAlgorithm.hmac_sha1);
-
-            case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256:
-            case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256:
-            case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256:
-            case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256:
-            case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256:
-            case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256:
-            case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256:
-            case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256:
-            case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256:
-                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.CAMELLIA_128_CBC, MacAlgorithm.hmac_sha256);
-
-            case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256:
-            case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256:
-            case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256:
-            case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256:
-            case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256:
-            case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256:
-            case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256:
-            case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256:
-            case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256:
-                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.CAMELLIA_128_GCM, MacAlgorithm.cls_null);
-
-            case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA:
-            case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA:
-            case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA:
-            case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA:
-            case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_CBC_SHA:
-                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.CAMELLIA_256_CBC, MacAlgorithm.hmac_sha1);
-
-            case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256:
-            case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256:
-            case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256:
-            case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256:
-            case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256:
-                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.CAMELLIA_256_CBC, MacAlgorithm.hmac_sha256);
-
-            case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384:
-            case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384:
-            case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384:
-            case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384:
-            case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384:
-            case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384:
-            case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384:
-            case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384:
-            case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384:
-                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.CAMELLIA_256_GCM, MacAlgorithm.cls_null);
-
-            case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384:
-            case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384:
-            case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384:
-            case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384:
-                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.CAMELLIA_256_CBC, MacAlgorithm.hmac_sha384);
-
-            case CipherSuite.TLS_DHE_RSA_WITH_ESTREAM_SALSA20_SHA1:
-            case CipherSuite.TLS_ECDHE_ECDSA_WITH_ESTREAM_SALSA20_SHA1:
-            case CipherSuite.TLS_ECDHE_RSA_WITH_ESTREAM_SALSA20_SHA1:
-            case CipherSuite.TLS_RSA_WITH_ESTREAM_SALSA20_SHA1:
-                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.ESTREAM_SALSA20, MacAlgorithm.hmac_sha1);
-
-            case CipherSuite.TLS_RSA_WITH_NULL_MD5:
-                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.NULL, MacAlgorithm.hmac_md5);
-
-            case CipherSuite.TLS_ECDH_ECDSA_WITH_NULL_SHA:
-            case CipherSuite.TLS_ECDH_RSA_WITH_NULL_SHA:
-            case CipherSuite.TLS_ECDHE_ECDSA_WITH_NULL_SHA:
-            case CipherSuite.TLS_ECDHE_RSA_WITH_NULL_SHA:
-            case CipherSuite.TLS_RSA_WITH_NULL_SHA:
-                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.NULL, MacAlgorithm.hmac_sha1);
-
-            case CipherSuite.TLS_RSA_WITH_NULL_SHA256:
-                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.NULL, MacAlgorithm.hmac_sha256);
-
-            case CipherSuite.TLS_RSA_WITH_RC4_128_MD5:
-                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.RC4_128, MacAlgorithm.hmac_md5);
-
-            case CipherSuite.TLS_ECDH_ECDSA_WITH_RC4_128_SHA:
-            case CipherSuite.TLS_ECDH_RSA_WITH_RC4_128_SHA:
-            case CipherSuite.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA:
-            case CipherSuite.TLS_ECDHE_RSA_WITH_RC4_128_SHA:
-            case CipherSuite.TLS_RSA_WITH_RC4_128_SHA:
-                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.RC4_128, MacAlgorithm.hmac_sha1);
-
-            case CipherSuite.TLS_DHE_RSA_WITH_SALSA20_SHA1:
-            case CipherSuite.TLS_ECDHE_ECDSA_WITH_SALSA20_SHA1:
-            case CipherSuite.TLS_ECDHE_RSA_WITH_SALSA20_SHA1:
-            case CipherSuite.TLS_RSA_WITH_SALSA20_SHA1:
-                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.SALSA20, MacAlgorithm.hmac_sha1);
-
-            case CipherSuite.TLS_DH_DSS_WITH_SEED_CBC_SHA:
-            case CipherSuite.TLS_DH_RSA_WITH_SEED_CBC_SHA:
-            case CipherSuite.TLS_DHE_DSS_WITH_SEED_CBC_SHA:
-            case CipherSuite.TLS_DHE_RSA_WITH_SEED_CBC_SHA:
-            case CipherSuite.TLS_RSA_WITH_SEED_CBC_SHA:
-                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.SEED_CBC, MacAlgorithm.hmac_sha1);
+            case KeyExchangeAlgorithm.RSA:
+                return CreateRsaKeyExchange();
 
             default:
                 /*
diff --git a/crypto/src/crypto/tls/DefaultTlsServer.cs b/crypto/src/crypto/tls/DefaultTlsServer.cs
index 156eff8af..b12c43e1c 100644
--- a/crypto/src/crypto/tls/DefaultTlsServer.cs
+++ b/crypto/src/crypto/tls/DefaultTlsServer.cs
@@ -72,542 +72,62 @@ namespace Org.BouncyCastle.Crypto.Tls
 
         public override TlsCredentials GetCredentials()
         {
-            switch (mSelectedCipherSuite)
+            int keyExchangeAlgorithm = TlsUtilities.GetKeyExchangeAlgorithm(mSelectedCipherSuite);
+
+            switch (keyExchangeAlgorithm)
             {
-            case CipherSuite.TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA:
-            case CipherSuite.TLS_DH_DSS_WITH_AES_128_CBC_SHA:
-            case CipherSuite.TLS_DH_DSS_WITH_AES_128_CBC_SHA256:
-            case CipherSuite.TLS_DH_DSS_WITH_AES_128_GCM_SHA256:
-            case CipherSuite.TLS_DH_DSS_WITH_AES_256_CBC_SHA:
-            case CipherSuite.TLS_DH_DSS_WITH_AES_256_CBC_SHA256:
-            case CipherSuite.TLS_DH_DSS_WITH_AES_256_GCM_SHA384:
-            case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA:
-            case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256:
-            case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256:
-            case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA:
-            case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256:
-            case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384:
-            case CipherSuite.TLS_DH_DSS_WITH_DES_CBC_SHA:
-            case CipherSuite.TLS_DH_DSS_WITH_SEED_CBC_SHA:
-            case CipherSuite.TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA:
-            case CipherSuite.TLS_DHE_DSS_WITH_AES_128_CBC_SHA:
-            case CipherSuite.TLS_DHE_DSS_WITH_AES_128_CBC_SHA256:
-            case CipherSuite.TLS_DHE_DSS_WITH_AES_128_GCM_SHA256:
-            case CipherSuite.TLS_DHE_DSS_WITH_AES_256_CBC_SHA:
-            case CipherSuite.TLS_DHE_DSS_WITH_AES_256_CBC_SHA256:
-            case CipherSuite.TLS_DHE_DSS_WITH_AES_256_GCM_SHA384:
-            case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA:
-            case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256:
-            case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256:
-            case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA:
-            case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256:
-            case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384:
-            case CipherSuite.TLS_DHE_DSS_WITH_DES_CBC_SHA:
-            case CipherSuite.TLS_DHE_DSS_WITH_SEED_CBC_SHA:
-            case CipherSuite.TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA:
-            case CipherSuite.TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA:
-            case CipherSuite.TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA:
-                return GetDsaSignerCredentials();
+                case KeyExchangeAlgorithm.DH_DSS:
+                case KeyExchangeAlgorithm.DHE_DSS:
+                    return GetDsaSignerCredentials();
 
-            case CipherSuite.TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA:
-            case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA:
-            case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256:
-            case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256:
-            case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA:
-            case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384:
-            case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384:
-            case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256:
-            case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256:
-            case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384:
-            case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384:
-            case CipherSuite.TLS_ECDH_ECDSA_WITH_NULL_SHA:
-            case CipherSuite.TLS_ECDH_ECDSA_WITH_RC4_128_SHA:
-            case CipherSuite.TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA:
-            case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA:
-            case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256:
-            case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CCM:
-            case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8:
-            case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256:
-            case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA:
-            case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384:
-            case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CCM:
-            case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8:
-            case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384:
-            case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256:
-            case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256:
-            case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384:
-            case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384:
-            case CipherSuite.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256:
-            case CipherSuite.TLS_ECDHE_ECDSA_WITH_ESTREAM_SALSA20_SHA1:
-            case CipherSuite.TLS_ECDHE_ECDSA_WITH_NULL_SHA:
-            case CipherSuite.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA:
-            case CipherSuite.TLS_ECDHE_ECDSA_WITH_SALSA20_SHA1:
-                return GetECDsaSignerCredentials();
+                case KeyExchangeAlgorithm.ECDH_ECDSA:
+                case KeyExchangeAlgorithm.ECDHE_ECDSA:
+                    return GetECDsaSignerCredentials();
 
-            case CipherSuite.TLS_RSA_WITH_3DES_EDE_CBC_SHA:
-            case CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA:
-            case CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA256:
-            case CipherSuite.TLS_RSA_WITH_AES_128_CCM:
-            case CipherSuite.TLS_RSA_WITH_AES_128_CCM_8:
-            case CipherSuite.TLS_RSA_WITH_AES_128_GCM_SHA256:
-            case CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA:
-            case CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA256:
-            case CipherSuite.TLS_RSA_WITH_AES_256_CCM:
-            case CipherSuite.TLS_RSA_WITH_AES_256_CCM_8:
-            case CipherSuite.TLS_RSA_WITH_AES_256_GCM_SHA384:
-            case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_CBC_SHA:
-            case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256:
-            case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256:
-            case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_CBC_SHA:
-            case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256:
-            case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384:
-            case CipherSuite.TLS_RSA_WITH_NULL_MD5:
-            case CipherSuite.TLS_RSA_WITH_NULL_SHA:
-            case CipherSuite.TLS_RSA_WITH_NULL_SHA256:
-            case CipherSuite.TLS_RSA_WITH_RC4_128_MD5:
-            case CipherSuite.TLS_RSA_WITH_RC4_128_SHA:
-            case CipherSuite.TLS_RSA_WITH_SEED_CBC_SHA:
-                return GetRsaEncryptionCredentials();
+                case KeyExchangeAlgorithm.DHE_RSA:
+                case KeyExchangeAlgorithm.ECDHE_RSA:
+                    return GetRsaSignerCredentials();
 
-            case CipherSuite.TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA:
-            case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA:
-            case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA256:
-            case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CCM:
-            case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CCM_8:
-            case CipherSuite.TLS_DHE_RSA_WITH_AES_128_GCM_SHA256:
-            case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA:
-            case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA256:
-            case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CCM:
-            case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CCM_8:
-            case CipherSuite.TLS_DHE_RSA_WITH_AES_256_GCM_SHA384:
-            case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA:
-            case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256:
-            case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256:
-            case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA:
-            case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256:
-            case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384:
-            case CipherSuite.TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256:
-            case CipherSuite.TLS_DHE_RSA_WITH_SEED_CBC_SHA:
-            case CipherSuite.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA:
-            case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA:
-            case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256:
-            case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256:
-            case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA:
-            case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384:
-            case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384:
-            case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256:
-            case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256:
-            case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384:
-            case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384:
-            case CipherSuite.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256:
-            case CipherSuite.TLS_ECDHE_RSA_WITH_ESTREAM_SALSA20_SHA1:
-            case CipherSuite.TLS_ECDHE_RSA_WITH_NULL_SHA:
-            case CipherSuite.TLS_ECDHE_RSA_WITH_RC4_128_SHA:
-            case CipherSuite.TLS_ECDHE_RSA_WITH_SALSA20_SHA1:
-                return GetRsaSignerCredentials();
+                case KeyExchangeAlgorithm.RSA:
+                    return GetRsaEncryptionCredentials();
 
-            default:
-                /*
-                 * Note: internal error here; selected a key exchange we don't implement!
-                 */
-                throw new TlsFatalAlert(AlertDescription.internal_error);
+                default:
+                    /* Note: internal error here; selected a key exchange we don't implement! */
+                    throw new TlsFatalAlert(AlertDescription.internal_error);
             }
         }
 
         public override TlsKeyExchange GetKeyExchange()
         {
-            switch (mSelectedCipherSuite)
-            {
-            case CipherSuite.TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA:
-            case CipherSuite.TLS_DH_DSS_WITH_AES_128_CBC_SHA:
-            case CipherSuite.TLS_DH_DSS_WITH_AES_128_CBC_SHA256:
-            case CipherSuite.TLS_DH_DSS_WITH_AES_128_GCM_SHA256:
-            case CipherSuite.TLS_DH_DSS_WITH_AES_256_CBC_SHA:
-            case CipherSuite.TLS_DH_DSS_WITH_AES_256_CBC_SHA256:
-            case CipherSuite.TLS_DH_DSS_WITH_AES_256_GCM_SHA384:
-            case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA:
-            case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256:
-            case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256:
-            case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA:
-            case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256:
-            case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384:
-            case CipherSuite.TLS_DH_DSS_WITH_SEED_CBC_SHA:
-                return CreateDHKeyExchange(KeyExchangeAlgorithm.DH_DSS);
-
-            case CipherSuite.TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA:
-            case CipherSuite.TLS_DH_RSA_WITH_AES_128_CBC_SHA:
-            case CipherSuite.TLS_DH_RSA_WITH_AES_128_CBC_SHA256:
-            case CipherSuite.TLS_DH_RSA_WITH_AES_128_GCM_SHA256:
-            case CipherSuite.TLS_DH_RSA_WITH_AES_256_CBC_SHA:
-            case CipherSuite.TLS_DH_RSA_WITH_AES_256_CBC_SHA256:
-            case CipherSuite.TLS_DH_RSA_WITH_AES_256_GCM_SHA384:
-            case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA:
-            case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256:
-            case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256:
-            case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA:
-            case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256:
-            case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384:
-            case CipherSuite.TLS_DH_RSA_WITH_SEED_CBC_SHA:
-                return CreateDHKeyExchange(KeyExchangeAlgorithm.DH_RSA);
-
-            case CipherSuite.TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA:
-            case CipherSuite.TLS_DHE_DSS_WITH_AES_128_CBC_SHA:
-            case CipherSuite.TLS_DHE_DSS_WITH_AES_128_CBC_SHA256:
-            case CipherSuite.TLS_DHE_DSS_WITH_AES_128_GCM_SHA256:
-            case CipherSuite.TLS_DHE_DSS_WITH_AES_256_CBC_SHA:
-            case CipherSuite.TLS_DHE_DSS_WITH_AES_256_CBC_SHA256:
-            case CipherSuite.TLS_DHE_DSS_WITH_AES_256_GCM_SHA384:
-            case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA:
-            case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256:
-            case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256:
-            case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA:
-            case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256:
-            case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384:
-            case CipherSuite.TLS_DHE_DSS_WITH_SEED_CBC_SHA:
-                return CreateDheKeyExchange(KeyExchangeAlgorithm.DHE_DSS);
-
-            case CipherSuite.TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA:
-            case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA:
-            case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA256:
-            case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CCM:
-            case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CCM_8:
-            case CipherSuite.TLS_DHE_RSA_WITH_AES_128_GCM_SHA256:
-            case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA:
-            case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA256:
-            case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CCM:
-            case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CCM_8:
-            case CipherSuite.TLS_DHE_RSA_WITH_AES_256_GCM_SHA384:
-            case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA:
-            case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256:
-            case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256:
-            case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA:
-            case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256:
-            case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384:
-            case CipherSuite.TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256:
-            case CipherSuite.TLS_DHE_RSA_WITH_ESTREAM_SALSA20_SHA1:
-            case CipherSuite.TLS_DHE_RSA_WITH_SALSA20_SHA1:
-            case CipherSuite.TLS_DHE_RSA_WITH_SEED_CBC_SHA:
-                return CreateDheKeyExchange(KeyExchangeAlgorithm.DHE_RSA);
-
-            case CipherSuite.TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA:
-            case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA:
-            case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256:
-            case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256:
-            case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA:
-            case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384:
-            case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384:
-            case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256:
-            case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256:
-            case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384:
-            case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384:
-            case CipherSuite.TLS_ECDH_ECDSA_WITH_NULL_SHA:
-            case CipherSuite.TLS_ECDH_ECDSA_WITH_RC4_128_SHA:
-                return CreateECDHKeyExchange(KeyExchangeAlgorithm.ECDH_ECDSA);
-
-            case CipherSuite.TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA:
-            case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_CBC_SHA:
-            case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256:
-            case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256:
-            case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_CBC_SHA:
-            case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384:
-            case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384:
-            case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256:
-            case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256:
-            case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384:
-            case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384:
-            case CipherSuite.TLS_ECDH_RSA_WITH_NULL_SHA:
-            case CipherSuite.TLS_ECDH_RSA_WITH_RC4_128_SHA:
-                return CreateECDHKeyExchange(KeyExchangeAlgorithm.ECDH_RSA);
-
-            case CipherSuite.TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA:
-            case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA:
-            case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256:
-            case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CCM:
-            case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8:
-            case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256:
-            case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA:
-            case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384:
-            case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CCM:
-            case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8:
-            case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384:
-            case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256:
-            case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256:
-            case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384:
-            case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384:
-            case CipherSuite.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256:
-            case CipherSuite.TLS_ECDHE_ECDSA_WITH_ESTREAM_SALSA20_SHA1:
-            case CipherSuite.TLS_ECDHE_ECDSA_WITH_NULL_SHA:
-            case CipherSuite.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA:
-            case CipherSuite.TLS_ECDHE_ECDSA_WITH_SALSA20_SHA1:
-                return CreateECDheKeyExchange(KeyExchangeAlgorithm.ECDHE_ECDSA);
+            int keyExchangeAlgorithm = TlsUtilities.GetKeyExchangeAlgorithm(mSelectedCipherSuite);
 
-            case CipherSuite.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA:
-            case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA:
-            case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256:
-            case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256:
-            case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA:
-            case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384:
-            case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384:
-            case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256:
-            case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256:
-            case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384:
-            case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384:
-            case CipherSuite.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256:
-            case CipherSuite.TLS_ECDHE_RSA_WITH_ESTREAM_SALSA20_SHA1:
-            case CipherSuite.TLS_ECDHE_RSA_WITH_NULL_SHA:
-            case CipherSuite.TLS_ECDHE_RSA_WITH_RC4_128_SHA:
-            case CipherSuite.TLS_ECDHE_RSA_WITH_SALSA20_SHA1:
-                return CreateECDheKeyExchange(KeyExchangeAlgorithm.ECDHE_RSA);
-
-            case CipherSuite.TLS_RSA_WITH_3DES_EDE_CBC_SHA:
-            case CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA:
-            case CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA256:
-            case CipherSuite.TLS_RSA_WITH_AES_128_CCM:
-            case CipherSuite.TLS_RSA_WITH_AES_128_CCM_8:
-            case CipherSuite.TLS_RSA_WITH_AES_128_GCM_SHA256:
-            case CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA:
-            case CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA256:
-            case CipherSuite.TLS_RSA_WITH_AES_256_CCM:
-            case CipherSuite.TLS_RSA_WITH_AES_256_CCM_8:
-            case CipherSuite.TLS_RSA_WITH_AES_256_GCM_SHA384:
-            case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_CBC_SHA:
-            case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256:
-            case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256:
-            case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_CBC_SHA:
-            case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256:
-            case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384:
-            case CipherSuite.TLS_RSA_WITH_ESTREAM_SALSA20_SHA1:
-            case CipherSuite.TLS_RSA_WITH_NULL_MD5:
-            case CipherSuite.TLS_RSA_WITH_NULL_SHA:
-            case CipherSuite.TLS_RSA_WITH_NULL_SHA256:
-            case CipherSuite.TLS_RSA_WITH_RC4_128_MD5:
-            case CipherSuite.TLS_RSA_WITH_RC4_128_SHA:
-            case CipherSuite.TLS_RSA_WITH_SALSA20_SHA1:
-            case CipherSuite.TLS_RSA_WITH_SEED_CBC_SHA:
-                return createRSAKeyExchange();
-
-            default:
-                /*
-                 * Note: internal error here; selected a key exchange we don't implement!
-                 */
-                throw new TlsFatalAlert(AlertDescription.internal_error);
-            }
-        }
-
-        public override TlsCipher GetCipher()
-        {
-            switch (mSelectedCipherSuite)
+            switch (keyExchangeAlgorithm)
             {
-            case CipherSuite.TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA:
-            case CipherSuite.TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA:
-            case CipherSuite.TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA:
-            case CipherSuite.TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA:
-            case CipherSuite.TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA:
-            case CipherSuite.TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA:
-            case CipherSuite.TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA:
-            case CipherSuite.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA:
-            case CipherSuite.TLS_RSA_WITH_3DES_EDE_CBC_SHA:
-                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.cls_3DES_EDE_CBC, MacAlgorithm.hmac_sha1);
-
-            case CipherSuite.TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256:
-            case CipherSuite.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256:
-            case CipherSuite.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256:
-                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AEAD_CHACHA20_POLY1305, MacAlgorithm.cls_null);
-
-            case CipherSuite.TLS_DH_DSS_WITH_AES_128_CBC_SHA:
-            case CipherSuite.TLS_DH_RSA_WITH_AES_128_CBC_SHA:
-            case CipherSuite.TLS_DHE_DSS_WITH_AES_128_CBC_SHA:
-            case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA:
-            case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA:
-            case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_CBC_SHA:
-            case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA:
-            case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA:
-            case CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA:
-                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_128_CBC, MacAlgorithm.hmac_sha1);
-
-            case CipherSuite.TLS_DH_DSS_WITH_AES_128_CBC_SHA256:
-            case CipherSuite.TLS_DH_RSA_WITH_AES_128_CBC_SHA256:
-            case CipherSuite.TLS_DHE_DSS_WITH_AES_128_CBC_SHA256:
-            case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA256:
-            case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256:
-            case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256:
-            case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256:
-            case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256:
-            case CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA256:
-                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_128_CBC, MacAlgorithm.hmac_sha256);
-
-            case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CCM:
-            case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CCM:
-            case CipherSuite.TLS_RSA_WITH_AES_128_CCM:
-                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_128_CCM, MacAlgorithm.cls_null);
-
-            case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CCM_8:
-            case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8:
-            case CipherSuite.TLS_RSA_WITH_AES_128_CCM_8:
-                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_128_CCM_8, MacAlgorithm.cls_null);
-
-            case CipherSuite.TLS_DH_DSS_WITH_AES_128_GCM_SHA256:
-            case CipherSuite.TLS_DH_RSA_WITH_AES_128_GCM_SHA256:
-            case CipherSuite.TLS_DHE_DSS_WITH_AES_128_GCM_SHA256:
-            case CipherSuite.TLS_DHE_RSA_WITH_AES_128_GCM_SHA256:
-            case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256:
-            case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256:
-            case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256:
-            case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256:
-            case CipherSuite.TLS_RSA_WITH_AES_128_GCM_SHA256:
-                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_128_GCM, MacAlgorithm.cls_null);
-
-            case CipherSuite.TLS_DH_DSS_WITH_AES_256_CBC_SHA:
-            case CipherSuite.TLS_DH_RSA_WITH_AES_256_CBC_SHA:
-            case CipherSuite.TLS_DHE_DSS_WITH_AES_256_CBC_SHA:
-            case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA:
-            case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA:
-            case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_CBC_SHA:
-            case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA:
-            case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA:
-            case CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA:
-                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_256_CBC, MacAlgorithm.hmac_sha1);
-
-            case CipherSuite.TLS_DH_DSS_WITH_AES_256_CBC_SHA256:
-            case CipherSuite.TLS_DH_RSA_WITH_AES_256_CBC_SHA256:
-            case CipherSuite.TLS_DHE_DSS_WITH_AES_256_CBC_SHA256:
-            case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA256:
-            case CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA256:
-                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_256_CBC, MacAlgorithm.hmac_sha256);
-
-            case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384:
-            case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384:
-            case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384:
-            case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384:
-                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_256_CBC, MacAlgorithm.hmac_sha384);
-
-            case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CCM:
-            case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CCM:
-            case CipherSuite.TLS_RSA_WITH_AES_256_CCM:
-                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_256_CCM, MacAlgorithm.cls_null);
-
-            case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CCM_8:
-            case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8:
-            case CipherSuite.TLS_RSA_WITH_AES_256_CCM_8:
-                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_256_CCM_8, MacAlgorithm.cls_null);
-
-            case CipherSuite.TLS_DH_DSS_WITH_AES_256_GCM_SHA384:
-            case CipherSuite.TLS_DH_RSA_WITH_AES_256_GCM_SHA384:
-            case CipherSuite.TLS_DHE_DSS_WITH_AES_256_GCM_SHA384:
-            case CipherSuite.TLS_DHE_RSA_WITH_AES_256_GCM_SHA384:
-            case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384:
-            case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384:
-            case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384:
-            case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384:
-            case CipherSuite.TLS_RSA_WITH_AES_256_GCM_SHA384:
-                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_256_GCM, MacAlgorithm.cls_null);
-
-            case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA:
-            case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA:
-            case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA:
-            case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA:
-            case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_CBC_SHA:
-                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.CAMELLIA_128_CBC, MacAlgorithm.hmac_sha1);
-
-            case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256:
-            case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256:
-            case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256:
-            case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256:
-            case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256:
-            case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256:
-            case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256:
-            case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256:
-            case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256:
-                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.CAMELLIA_128_CBC, MacAlgorithm.hmac_sha256);
-
-            case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256:
-            case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256:
-            case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256:
-            case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256:
-            case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256:
-            case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256:
-            case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256:
-            case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256:
-            case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256:
-                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.CAMELLIA_128_GCM, MacAlgorithm.cls_null);
-
-            case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA:
-            case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA:
-            case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA:
-            case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA:
-            case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_CBC_SHA:
-                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.CAMELLIA_256_CBC, MacAlgorithm.hmac_sha1);
-
-            case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256:
-            case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256:
-            case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256:
-            case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256:
-            case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256:
-                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.CAMELLIA_256_CBC, MacAlgorithm.hmac_sha256);
-
-            case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384:
-            case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384:
-            case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384:
-            case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384:
-            case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384:
-            case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384:
-            case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384:
-            case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384:
-            case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384:
-                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.CAMELLIA_256_GCM, MacAlgorithm.cls_null);
-
-            case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384:
-            case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384:
-            case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384:
-            case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384:
-                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.CAMELLIA_256_CBC, MacAlgorithm.hmac_sha384);
-
-            case CipherSuite.TLS_DHE_RSA_WITH_ESTREAM_SALSA20_SHA1:
-            case CipherSuite.TLS_ECDHE_ECDSA_WITH_ESTREAM_SALSA20_SHA1:
-            case CipherSuite.TLS_ECDHE_RSA_WITH_ESTREAM_SALSA20_SHA1:
-            case CipherSuite.TLS_RSA_WITH_ESTREAM_SALSA20_SHA1:
-                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.ESTREAM_SALSA20, MacAlgorithm.hmac_sha1);
-
-            case CipherSuite.TLS_RSA_WITH_NULL_MD5:
-                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.NULL, MacAlgorithm.hmac_md5);
-
-            case CipherSuite.TLS_ECDH_ECDSA_WITH_NULL_SHA:
-            case CipherSuite.TLS_ECDH_RSA_WITH_NULL_SHA:
-            case CipherSuite.TLS_ECDHE_ECDSA_WITH_NULL_SHA:
-            case CipherSuite.TLS_ECDHE_RSA_WITH_NULL_SHA:
-            case CipherSuite.TLS_RSA_WITH_NULL_SHA:
-                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.NULL, MacAlgorithm.hmac_sha1);
-
-            case CipherSuite.TLS_RSA_WITH_NULL_SHA256:
-                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.NULL, MacAlgorithm.hmac_sha256);
+            case KeyExchangeAlgorithm.DH_DSS:
+            case KeyExchangeAlgorithm.DH_RSA:
+                return CreateDHKeyExchange(keyExchangeAlgorithm);
 
-            case CipherSuite.TLS_RSA_WITH_RC4_128_MD5:
-                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.RC4_128, MacAlgorithm.hmac_md5);
+            case KeyExchangeAlgorithm.DHE_DSS:
+            case KeyExchangeAlgorithm.DHE_RSA:
+                return CreateDheKeyExchange(keyExchangeAlgorithm);
 
-            case CipherSuite.TLS_ECDH_ECDSA_WITH_RC4_128_SHA:
-            case CipherSuite.TLS_ECDH_RSA_WITH_RC4_128_SHA:
-            case CipherSuite.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA:
-            case CipherSuite.TLS_ECDHE_RSA_WITH_RC4_128_SHA:
-            case CipherSuite.TLS_RSA_WITH_RC4_128_SHA:
-                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.RC4_128, MacAlgorithm.hmac_sha1);
+            case KeyExchangeAlgorithm.ECDH_ECDSA:
+            case KeyExchangeAlgorithm.ECDH_RSA:
+                return CreateECDHKeyExchange(keyExchangeAlgorithm);
 
-            case CipherSuite.TLS_DHE_RSA_WITH_SALSA20_SHA1:
-            case CipherSuite.TLS_ECDHE_ECDSA_WITH_SALSA20_SHA1:
-            case CipherSuite.TLS_ECDHE_RSA_WITH_SALSA20_SHA1:
-            case CipherSuite.TLS_RSA_WITH_SALSA20_SHA1:
-                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.SALSA20, MacAlgorithm.hmac_sha1);
+            case KeyExchangeAlgorithm.ECDHE_ECDSA:
+            case KeyExchangeAlgorithm.ECDHE_RSA:
+                return CreateECDheKeyExchange(keyExchangeAlgorithm);
 
-            case CipherSuite.TLS_DH_DSS_WITH_SEED_CBC_SHA:
-            case CipherSuite.TLS_DH_RSA_WITH_SEED_CBC_SHA:
-            case CipherSuite.TLS_DHE_DSS_WITH_SEED_CBC_SHA:
-            case CipherSuite.TLS_DHE_RSA_WITH_SEED_CBC_SHA:
-            case CipherSuite.TLS_RSA_WITH_SEED_CBC_SHA:
-                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.SEED_CBC, MacAlgorithm.hmac_sha1);
+            case KeyExchangeAlgorithm.RSA:
+                return CreateRsaKeyExchange();
 
             default:
                 /*
-                 * Note: internal error here; selected a cipher suite we don't implement!
-                 */
+                    * Note: internal error here; the TlsProtocol implementation verifies that the
+                    * server-selected cipher suite was in the list of client-offered cipher suites, so if
+                    * we now can't produce an implementation, we shouldn't have offered it!
+                    */
                 throw new TlsFatalAlert(AlertDescription.internal_error);
             }
         }
@@ -634,7 +154,7 @@ namespace Org.BouncyCastle.Crypto.Tls
                 mServerECPointFormats);
         }
 
-        protected virtual TlsKeyExchange createRSAKeyExchange()
+        protected virtual TlsKeyExchange CreateRsaKeyExchange()
         {
             return new TlsRsaKeyExchange(mSupportedSignatureAlgorithms);
         }
diff --git a/crypto/src/crypto/tls/PskTlsClient.cs b/crypto/src/crypto/tls/PskTlsClient.cs
index 1f4b0865c..2ef80dcfd 100644
--- a/crypto/src/crypto/tls/PskTlsClient.cs
+++ b/crypto/src/crypto/tls/PskTlsClient.cs
@@ -32,87 +32,15 @@ namespace Org.BouncyCastle.Crypto.Tls
 
         public override TlsKeyExchange GetKeyExchange()
         {
-            switch (mSelectedCipherSuite)
-            {
-            case CipherSuite.TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA:
-            case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CBC_SHA:
-            case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CBC_SHA256:
-            case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CCM:
-            case CipherSuite.TLS_DHE_PSK_WITH_AES_128_GCM_SHA256:
-            case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CBC_SHA:
-            case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CBC_SHA384:
-            case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CCM:
-            case CipherSuite.TLS_DHE_PSK_WITH_AES_256_GCM_SHA384:
-            case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256:
-            case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256:
-            case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384:
-            case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384:
-            case CipherSuite.TLS_DHE_PSK_WITH_ESTREAM_SALSA20_SHA1:
-            case CipherSuite.TLS_DHE_PSK_WITH_NULL_SHA:
-            case CipherSuite.TLS_DHE_PSK_WITH_NULL_SHA256:
-            case CipherSuite.TLS_DHE_PSK_WITH_NULL_SHA384:
-            case CipherSuite.TLS_DHE_PSK_WITH_RC4_128_SHA:
-            case CipherSuite.TLS_DHE_PSK_WITH_SALSA20_SHA1:
-            case CipherSuite.TLS_PSK_DHE_WITH_AES_128_CCM_8:
-            case CipherSuite.TLS_PSK_DHE_WITH_AES_256_CCM_8:
-                return CreatePskKeyExchange(KeyExchangeAlgorithm.DHE_PSK);
-
-            case CipherSuite.TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA:
-            case CipherSuite.TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA:
-            case CipherSuite.TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256:
-            case CipherSuite.TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA:
-            case CipherSuite.TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384:
-            case CipherSuite.TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256:
-            case CipherSuite.TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384:
-            case CipherSuite.TLS_ECDHE_PSK_WITH_ESTREAM_SALSA20_SHA1:
-            case CipherSuite.TLS_ECDHE_PSK_WITH_NULL_SHA:
-            case CipherSuite.TLS_ECDHE_PSK_WITH_NULL_SHA256:
-            case CipherSuite.TLS_ECDHE_PSK_WITH_NULL_SHA384:
-            case CipherSuite.TLS_ECDHE_PSK_WITH_RC4_128_SHA:
-            case CipherSuite.TLS_ECDHE_PSK_WITH_SALSA20_SHA1:
-                return CreatePskKeyExchange(KeyExchangeAlgorithm.ECDHE_PSK);
-
-            case CipherSuite.TLS_PSK_WITH_3DES_EDE_CBC_SHA:
-            case CipherSuite.TLS_PSK_WITH_AES_128_CBC_SHA:
-            case CipherSuite.TLS_PSK_WITH_AES_128_CBC_SHA256:
-            case CipherSuite.TLS_PSK_WITH_AES_128_CCM:
-            case CipherSuite.TLS_PSK_WITH_AES_128_CCM_8:
-            case CipherSuite.TLS_PSK_WITH_AES_128_GCM_SHA256:
-            case CipherSuite.TLS_PSK_WITH_AES_256_CBC_SHA:
-            case CipherSuite.TLS_PSK_WITH_AES_256_CBC_SHA384:
-            case CipherSuite.TLS_PSK_WITH_AES_256_CCM:
-            case CipherSuite.TLS_PSK_WITH_AES_256_CCM_8:
-            case CipherSuite.TLS_PSK_WITH_AES_256_GCM_SHA384:
-            case CipherSuite.TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256:
-            case CipherSuite.TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256:
-            case CipherSuite.TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384:
-            case CipherSuite.TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384:
-            case CipherSuite.TLS_PSK_WITH_ESTREAM_SALSA20_SHA1:
-            case CipherSuite.TLS_PSK_WITH_NULL_SHA:
-            case CipherSuite.TLS_PSK_WITH_NULL_SHA256:
-            case CipherSuite.TLS_PSK_WITH_NULL_SHA384:
-            case CipherSuite.TLS_PSK_WITH_RC4_128_SHA:
-            case CipherSuite.TLS_PSK_WITH_SALSA20_SHA1:
-                return CreatePskKeyExchange(KeyExchangeAlgorithm.PSK);
+            int keyExchangeAlgorithm = TlsUtilities.GetKeyExchangeAlgorithm(mSelectedCipherSuite);
 
-            case CipherSuite.TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA:
-            case CipherSuite.TLS_RSA_PSK_WITH_AES_128_CBC_SHA:
-            case CipherSuite.TLS_RSA_PSK_WITH_AES_128_CBC_SHA256:
-            case CipherSuite.TLS_RSA_PSK_WITH_AES_128_GCM_SHA256:
-            case CipherSuite.TLS_RSA_PSK_WITH_AES_256_CBC_SHA:
-            case CipherSuite.TLS_RSA_PSK_WITH_AES_256_CBC_SHA384:
-            case CipherSuite.TLS_RSA_PSK_WITH_AES_256_GCM_SHA384:
-            case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256:
-            case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256:
-            case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384:
-            case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384:
-            case CipherSuite.TLS_RSA_PSK_WITH_ESTREAM_SALSA20_SHA1:
-            case CipherSuite.TLS_RSA_PSK_WITH_NULL_SHA:
-            case CipherSuite.TLS_RSA_PSK_WITH_NULL_SHA256:
-            case CipherSuite.TLS_RSA_PSK_WITH_NULL_SHA384:
-            case CipherSuite.TLS_RSA_PSK_WITH_RC4_128_SHA:
-            case CipherSuite.TLS_RSA_PSK_WITH_SALSA20_SHA1:
-                return CreatePskKeyExchange(KeyExchangeAlgorithm.RSA_PSK);
+            switch (keyExchangeAlgorithm)
+            {
+            case KeyExchangeAlgorithm.DHE_PSK:
+            case KeyExchangeAlgorithm.ECDHE_PSK:
+            case KeyExchangeAlgorithm.PSK:
+            case KeyExchangeAlgorithm.RSA_PSK:
+                return CreatePskKeyExchange(keyExchangeAlgorithm);
 
             default:
                 /*
@@ -133,134 +61,6 @@ namespace Org.BouncyCastle.Crypto.Tls
             throw new TlsFatalAlert(AlertDescription.internal_error);
         }
 
-        public override TlsCipher GetCipher()
-        {
-            switch (mSelectedCipherSuite)
-            {
-            case CipherSuite.TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA:
-            case CipherSuite.TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA:
-            case CipherSuite.TLS_PSK_WITH_3DES_EDE_CBC_SHA:
-            case CipherSuite.TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA:
-                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.cls_3DES_EDE_CBC, MacAlgorithm.hmac_sha1);
-
-            case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CBC_SHA:
-            case CipherSuite.TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA:
-            case CipherSuite.TLS_PSK_WITH_AES_128_CBC_SHA:
-            case CipherSuite.TLS_RSA_PSK_WITH_AES_128_CBC_SHA:
-                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_128_CBC, MacAlgorithm.hmac_sha1);
-
-            case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CBC_SHA256:
-            case CipherSuite.TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256:
-            case CipherSuite.TLS_PSK_WITH_AES_128_CBC_SHA256:
-            case CipherSuite.TLS_RSA_PSK_WITH_AES_128_CBC_SHA256:
-                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_128_CBC, MacAlgorithm.hmac_sha256);
-
-            case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CCM:
-            case CipherSuite.TLS_PSK_WITH_AES_128_CCM:
-                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_128_CCM, MacAlgorithm.cls_null);
-
-            case CipherSuite.TLS_PSK_DHE_WITH_AES_128_CCM_8:
-            case CipherSuite.TLS_PSK_WITH_AES_128_CCM_8:
-                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_128_CCM_8, MacAlgorithm.cls_null);
-
-            case CipherSuite.TLS_DHE_PSK_WITH_AES_128_GCM_SHA256:
-            case CipherSuite.TLS_PSK_WITH_AES_128_GCM_SHA256:
-            case CipherSuite.TLS_RSA_PSK_WITH_AES_128_GCM_SHA256:
-                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_128_GCM, MacAlgorithm.cls_null);
-
-            case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CBC_SHA:
-            case CipherSuite.TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA:
-            case CipherSuite.TLS_PSK_WITH_AES_256_CBC_SHA:
-            case CipherSuite.TLS_RSA_PSK_WITH_AES_256_CBC_SHA:
-                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_256_CBC, MacAlgorithm.hmac_sha1);
-
-            case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CBC_SHA384:
-            case CipherSuite.TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384:
-            case CipherSuite.TLS_PSK_WITH_AES_256_CBC_SHA384:
-            case CipherSuite.TLS_RSA_PSK_WITH_AES_256_CBC_SHA384:
-                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_256_CBC, MacAlgorithm.hmac_sha384);
-
-            case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CCM:
-            case CipherSuite.TLS_PSK_WITH_AES_256_CCM:
-                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_256_CCM, MacAlgorithm.cls_null);
-
-            case CipherSuite.TLS_PSK_DHE_WITH_AES_256_CCM_8:
-            case CipherSuite.TLS_PSK_WITH_AES_256_CCM_8:
-                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_256_CCM_8, MacAlgorithm.cls_null);
-
-            case CipherSuite.TLS_DHE_PSK_WITH_AES_256_GCM_SHA384:
-            case CipherSuite.TLS_PSK_WITH_AES_256_GCM_SHA384:
-            case CipherSuite.TLS_RSA_PSK_WITH_AES_256_GCM_SHA384:
-                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_256_GCM, MacAlgorithm.cls_null);
-
-            case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256:
-            case CipherSuite.TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256:
-            case CipherSuite.TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256:
-            case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256:
-                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.CAMELLIA_128_CBC, MacAlgorithm.hmac_sha256);
-
-            case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256:
-            case CipherSuite.TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256:
-            case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256:
-                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.CAMELLIA_128_GCM, MacAlgorithm.cls_null);
-
-            case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384:
-            case CipherSuite.TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384:
-            case CipherSuite.TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384:
-            case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384:
-                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.CAMELLIA_256_CBC, MacAlgorithm.hmac_sha384);
-
-            case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384:
-            case CipherSuite.TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384:
-            case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384:
-                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.CAMELLIA_256_GCM, MacAlgorithm.cls_null);
-
-            case CipherSuite.TLS_DHE_PSK_WITH_ESTREAM_SALSA20_SHA1:
-            case CipherSuite.TLS_ECDHE_PSK_WITH_ESTREAM_SALSA20_SHA1:
-            case CipherSuite.TLS_PSK_WITH_ESTREAM_SALSA20_SHA1:
-            case CipherSuite.TLS_RSA_PSK_WITH_ESTREAM_SALSA20_SHA1:
-                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.ESTREAM_SALSA20, MacAlgorithm.hmac_sha1);
-
-            case CipherSuite.TLS_DHE_PSK_WITH_NULL_SHA:
-            case CipherSuite.TLS_ECDHE_PSK_WITH_NULL_SHA:
-            case CipherSuite.TLS_PSK_WITH_NULL_SHA:
-            case CipherSuite.TLS_RSA_PSK_WITH_NULL_SHA:
-                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.NULL, MacAlgorithm.hmac_sha1);
-
-            case CipherSuite.TLS_DHE_PSK_WITH_NULL_SHA256:
-            case CipherSuite.TLS_ECDHE_PSK_WITH_NULL_SHA256:
-            case CipherSuite.TLS_PSK_WITH_NULL_SHA256:
-            case CipherSuite.TLS_RSA_PSK_WITH_NULL_SHA256:
-                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.NULL, MacAlgorithm.hmac_sha256);
-
-            case CipherSuite.TLS_DHE_PSK_WITH_NULL_SHA384:
-            case CipherSuite.TLS_ECDHE_PSK_WITH_NULL_SHA384:
-            case CipherSuite.TLS_PSK_WITH_NULL_SHA384:
-            case CipherSuite.TLS_RSA_PSK_WITH_NULL_SHA384:
-                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.NULL, MacAlgorithm.hmac_sha384);
-
-            case CipherSuite.TLS_DHE_PSK_WITH_RC4_128_SHA:
-            case CipherSuite.TLS_ECDHE_PSK_WITH_RC4_128_SHA:
-            case CipherSuite.TLS_PSK_WITH_RC4_128_SHA:
-            case CipherSuite.TLS_RSA_PSK_WITH_RC4_128_SHA:
-                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.RC4_128, MacAlgorithm.hmac_sha1);
-
-            case CipherSuite.TLS_DHE_PSK_WITH_SALSA20_SHA1:
-            case CipherSuite.TLS_ECDHE_PSK_WITH_SALSA20_SHA1:
-            case CipherSuite.TLS_PSK_WITH_SALSA20_SHA1:
-            case CipherSuite.TLS_RSA_PSK_WITH_SALSA20_SHA1:
-                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.SALSA20, MacAlgorithm.hmac_sha1);
-
-            default:
-                /*
-                    * Note: internal error here; the TlsProtocol implementation verifies that the
-                    * server-selected cipher suite was in the list of client-offered cipher suites, so if
-                    * we now can't produce an implementation, we shouldn't have offered it!
-                    */
-                throw new TlsFatalAlert(AlertDescription.internal_error);
-            }
-        }
-
         protected virtual TlsKeyExchange CreatePskKeyExchange(int keyExchange)
         {
             return new TlsPskKeyExchange(keyExchange, mSupportedSignatureAlgorithms, mPskIdentity, null, null, mNamedCurves,
diff --git a/crypto/src/crypto/tls/PskTlsServer.cs b/crypto/src/crypto/tls/PskTlsServer.cs
index 335c9de86..27d2b8119 100644
--- a/crypto/src/crypto/tls/PskTlsServer.cs
+++ b/crypto/src/crypto/tls/PskTlsServer.cs
@@ -44,297 +44,43 @@ namespace Org.BouncyCastle.Crypto.Tls
 
         public override TlsCredentials GetCredentials()
         {
-            switch (mSelectedCipherSuite)
-            {
-            case CipherSuite.TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA:
-            case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CBC_SHA:
-            case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CBC_SHA256:
-            case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CCM:
-            case CipherSuite.TLS_DHE_PSK_WITH_AES_128_GCM_SHA256:
-            case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CBC_SHA:
-            case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CBC_SHA384:
-            case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CCM:
-            case CipherSuite.TLS_DHE_PSK_WITH_AES_256_GCM_SHA384:
-            case CipherSuite.TLS_DHE_PSK_WITH_ESTREAM_SALSA20_SHA1:
-            case CipherSuite.TLS_DHE_PSK_WITH_NULL_SHA:
-            case CipherSuite.TLS_DHE_PSK_WITH_NULL_SHA256:
-            case CipherSuite.TLS_DHE_PSK_WITH_NULL_SHA384:
-            case CipherSuite.TLS_DHE_PSK_WITH_RC4_128_SHA:
-            case CipherSuite.TLS_DHE_PSK_WITH_SALSA20_SHA1:
-            case CipherSuite.TLS_PSK_DHE_WITH_AES_128_CCM_8:
-            case CipherSuite.TLS_PSK_DHE_WITH_AES_256_CCM_8:
-
-            case CipherSuite.TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA:
-            case CipherSuite.TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA:
-            case CipherSuite.TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256:
-            case CipherSuite.TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA:
-            case CipherSuite.TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384:
-            case CipherSuite.TLS_ECDHE_PSK_WITH_ESTREAM_SALSA20_SHA1:
-            case CipherSuite.TLS_ECDHE_PSK_WITH_NULL_SHA:
-            case CipherSuite.TLS_ECDHE_PSK_WITH_NULL_SHA256:
-            case CipherSuite.TLS_ECDHE_PSK_WITH_NULL_SHA384:
-            case CipherSuite.TLS_ECDHE_PSK_WITH_RC4_128_SHA:
-            case CipherSuite.TLS_ECDHE_PSK_WITH_SALSA20_SHA1:
+            int keyExchangeAlgorithm = TlsUtilities.GetKeyExchangeAlgorithm(mSelectedCipherSuite);
 
-            case CipherSuite.TLS_PSK_WITH_3DES_EDE_CBC_SHA:
-            case CipherSuite.TLS_PSK_WITH_AES_128_CBC_SHA:
-            case CipherSuite.TLS_PSK_WITH_AES_128_CBC_SHA256:
-            case CipherSuite.TLS_PSK_WITH_AES_128_CCM:
-            case CipherSuite.TLS_PSK_WITH_AES_128_CCM_8:
-            case CipherSuite.TLS_PSK_WITH_AES_128_GCM_SHA256:
-            case CipherSuite.TLS_PSK_WITH_AES_256_CBC_SHA:
-            case CipherSuite.TLS_PSK_WITH_AES_256_CBC_SHA384:
-            case CipherSuite.TLS_PSK_WITH_AES_256_CCM:
-            case CipherSuite.TLS_PSK_WITH_AES_256_CCM_8:
-            case CipherSuite.TLS_PSK_WITH_AES_256_GCM_SHA384:
-            case CipherSuite.TLS_PSK_WITH_ESTREAM_SALSA20_SHA1:
-            case CipherSuite.TLS_PSK_WITH_NULL_SHA:
-            case CipherSuite.TLS_PSK_WITH_NULL_SHA256:
-            case CipherSuite.TLS_PSK_WITH_NULL_SHA384:
-            case CipherSuite.TLS_PSK_WITH_RC4_128_SHA:
-            case CipherSuite.TLS_PSK_WITH_SALSA20_SHA1:
-                return null;
+            switch (keyExchangeAlgorithm)
+            {
+                case KeyExchangeAlgorithm.DHE_PSK:
+                case KeyExchangeAlgorithm.ECDHE_PSK:
+                case KeyExchangeAlgorithm.PSK:
+                    return null;
 
-            case CipherSuite.TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA:
-            case CipherSuite.TLS_RSA_PSK_WITH_AES_128_CBC_SHA:
-            case CipherSuite.TLS_RSA_PSK_WITH_AES_128_CBC_SHA256:
-            case CipherSuite.TLS_RSA_PSK_WITH_AES_128_GCM_SHA256:
-            case CipherSuite.TLS_RSA_PSK_WITH_AES_256_CBC_SHA:
-            case CipherSuite.TLS_RSA_PSK_WITH_AES_256_CBC_SHA384:
-            case CipherSuite.TLS_RSA_PSK_WITH_AES_256_GCM_SHA384:
-            case CipherSuite.TLS_RSA_PSK_WITH_ESTREAM_SALSA20_SHA1:
-            case CipherSuite.TLS_RSA_PSK_WITH_NULL_SHA:
-            case CipherSuite.TLS_RSA_PSK_WITH_NULL_SHA256:
-            case CipherSuite.TLS_RSA_PSK_WITH_NULL_SHA384:
-            case CipherSuite.TLS_RSA_PSK_WITH_RC4_128_SHA:
-            case CipherSuite.TLS_RSA_PSK_WITH_SALSA20_SHA1:
-                return GetRsaEncryptionCredentials();
+                case KeyExchangeAlgorithm.RSA_PSK:
+                    return GetRsaEncryptionCredentials();
 
-            default:
-                /* Note: internal error here; selected a key exchange we don't implement! */
-                throw new TlsFatalAlert(AlertDescription.internal_error);
+                default:
+                    /* Note: internal error here; selected a key exchange we don't implement! */
+                    throw new TlsFatalAlert(AlertDescription.internal_error);
             }
         }
 
         public override TlsKeyExchange GetKeyExchange()
         {
-            switch (mSelectedCipherSuite)
-            {
-            case CipherSuite.TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA:
-            case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CBC_SHA:
-            case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CBC_SHA256:
-            case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CCM:
-            case CipherSuite.TLS_DHE_PSK_WITH_AES_128_GCM_SHA256:
-            case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CBC_SHA:
-            case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CBC_SHA384:
-            case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CCM:
-            case CipherSuite.TLS_DHE_PSK_WITH_AES_256_GCM_SHA384:
-            case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256:
-            case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256:
-            case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384:
-            case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384:
-            case CipherSuite.TLS_DHE_PSK_WITH_ESTREAM_SALSA20_SHA1:
-            case CipherSuite.TLS_DHE_PSK_WITH_NULL_SHA:
-            case CipherSuite.TLS_DHE_PSK_WITH_NULL_SHA256:
-            case CipherSuite.TLS_DHE_PSK_WITH_NULL_SHA384:
-            case CipherSuite.TLS_DHE_PSK_WITH_RC4_128_SHA:
-            case CipherSuite.TLS_DHE_PSK_WITH_SALSA20_SHA1:
-            case CipherSuite.TLS_PSK_DHE_WITH_AES_128_CCM_8:
-            case CipherSuite.TLS_PSK_DHE_WITH_AES_256_CCM_8:
-                return CreatePskKeyExchange(KeyExchangeAlgorithm.DHE_PSK);
-
-            case CipherSuite.TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA:
-            case CipherSuite.TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA:
-            case CipherSuite.TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256:
-            case CipherSuite.TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA:
-            case CipherSuite.TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384:
-            case CipherSuite.TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256:
-            case CipherSuite.TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384:
-            case CipherSuite.TLS_ECDHE_PSK_WITH_ESTREAM_SALSA20_SHA1:
-            case CipherSuite.TLS_ECDHE_PSK_WITH_NULL_SHA:
-            case CipherSuite.TLS_ECDHE_PSK_WITH_NULL_SHA256:
-            case CipherSuite.TLS_ECDHE_PSK_WITH_NULL_SHA384:
-            case CipherSuite.TLS_ECDHE_PSK_WITH_RC4_128_SHA:
-            case CipherSuite.TLS_ECDHE_PSK_WITH_SALSA20_SHA1:
-                return CreatePskKeyExchange(KeyExchangeAlgorithm.ECDHE_PSK);
-
-            case CipherSuite.TLS_PSK_WITH_3DES_EDE_CBC_SHA:
-            case CipherSuite.TLS_PSK_WITH_AES_128_CBC_SHA:
-            case CipherSuite.TLS_PSK_WITH_AES_128_CBC_SHA256:
-            case CipherSuite.TLS_PSK_WITH_AES_128_CCM:
-            case CipherSuite.TLS_PSK_WITH_AES_128_CCM_8:
-            case CipherSuite.TLS_PSK_WITH_AES_128_GCM_SHA256:
-            case CipherSuite.TLS_PSK_WITH_AES_256_CBC_SHA:
-            case CipherSuite.TLS_PSK_WITH_AES_256_CBC_SHA384:
-            case CipherSuite.TLS_PSK_WITH_AES_256_CCM:
-            case CipherSuite.TLS_PSK_WITH_AES_256_CCM_8:
-            case CipherSuite.TLS_PSK_WITH_AES_256_GCM_SHA384:
-            case CipherSuite.TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256:
-            case CipherSuite.TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256:
-            case CipherSuite.TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384:
-            case CipherSuite.TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384:
-            case CipherSuite.TLS_PSK_WITH_ESTREAM_SALSA20_SHA1:
-            case CipherSuite.TLS_PSK_WITH_NULL_SHA:
-            case CipherSuite.TLS_PSK_WITH_NULL_SHA256:
-            case CipherSuite.TLS_PSK_WITH_NULL_SHA384:
-            case CipherSuite.TLS_PSK_WITH_RC4_128_SHA:
-            case CipherSuite.TLS_PSK_WITH_SALSA20_SHA1:
-                return CreatePskKeyExchange(KeyExchangeAlgorithm.PSK);
-
-            case CipherSuite.TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA:
-            case CipherSuite.TLS_RSA_PSK_WITH_AES_128_CBC_SHA:
-            case CipherSuite.TLS_RSA_PSK_WITH_AES_128_CBC_SHA256:
-            case CipherSuite.TLS_RSA_PSK_WITH_AES_128_GCM_SHA256:
-            case CipherSuite.TLS_RSA_PSK_WITH_AES_256_CBC_SHA:
-            case CipherSuite.TLS_RSA_PSK_WITH_AES_256_CBC_SHA384:
-            case CipherSuite.TLS_RSA_PSK_WITH_AES_256_GCM_SHA384:
-            case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256:
-            case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256:
-            case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384:
-            case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384:
-            case CipherSuite.TLS_RSA_PSK_WITH_ESTREAM_SALSA20_SHA1:
-            case CipherSuite.TLS_RSA_PSK_WITH_NULL_SHA:
-            case CipherSuite.TLS_RSA_PSK_WITH_NULL_SHA256:
-            case CipherSuite.TLS_RSA_PSK_WITH_NULL_SHA384:
-            case CipherSuite.TLS_RSA_PSK_WITH_RC4_128_SHA:
-            case CipherSuite.TLS_RSA_PSK_WITH_SALSA20_SHA1:
-                return CreatePskKeyExchange(KeyExchangeAlgorithm.RSA_PSK);
-
-            default:
-                /*
-                 * Note: internal error here; the TlsProtocol implementation verifies that the
-                 * server-selected cipher suite was in the list of client-offered cipher suites, so if
-                 * we now can't produce an implementation, we shouldn't have offered it!
-                 */
-                throw new TlsFatalAlert(AlertDescription.internal_error);
-            }
-        }
+            int keyExchangeAlgorithm = TlsUtilities.GetKeyExchangeAlgorithm(mSelectedCipherSuite);
 
-        public override TlsCipher GetCipher()
-        {
-            switch (mSelectedCipherSuite)
+            switch (keyExchangeAlgorithm)
             {
-            case CipherSuite.TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA:
-            case CipherSuite.TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA:
-            case CipherSuite.TLS_PSK_WITH_3DES_EDE_CBC_SHA:
-            case CipherSuite.TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA:
-                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.cls_3DES_EDE_CBC, MacAlgorithm.hmac_sha1);
-
-            case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CBC_SHA:
-            case CipherSuite.TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA:
-            case CipherSuite.TLS_PSK_WITH_AES_128_CBC_SHA:
-            case CipherSuite.TLS_RSA_PSK_WITH_AES_128_CBC_SHA:
-                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_128_CBC, MacAlgorithm.hmac_sha1);
-
-            case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CBC_SHA256:
-            case CipherSuite.TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256:
-            case CipherSuite.TLS_PSK_WITH_AES_128_CBC_SHA256:
-            case CipherSuite.TLS_RSA_PSK_WITH_AES_128_CBC_SHA256:
-                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_128_CBC, MacAlgorithm.hmac_sha256);
-
-            case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CCM:
-            case CipherSuite.TLS_PSK_WITH_AES_128_CCM:
-                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_128_CCM, MacAlgorithm.cls_null);
-
-            case CipherSuite.TLS_PSK_DHE_WITH_AES_128_CCM_8:
-            case CipherSuite.TLS_PSK_WITH_AES_128_CCM_8:
-                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_128_CCM_8, MacAlgorithm.cls_null);
-
-            case CipherSuite.TLS_DHE_PSK_WITH_AES_128_GCM_SHA256:
-            case CipherSuite.TLS_PSK_WITH_AES_128_GCM_SHA256:
-            case CipherSuite.TLS_RSA_PSK_WITH_AES_128_GCM_SHA256:
-                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_128_GCM, MacAlgorithm.cls_null);
-
-            case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CBC_SHA:
-            case CipherSuite.TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA:
-            case CipherSuite.TLS_PSK_WITH_AES_256_CBC_SHA:
-            case CipherSuite.TLS_RSA_PSK_WITH_AES_256_CBC_SHA:
-                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_256_CBC, MacAlgorithm.hmac_sha1);
-
-            case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CBC_SHA384:
-            case CipherSuite.TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384:
-            case CipherSuite.TLS_PSK_WITH_AES_256_CBC_SHA384:
-            case CipherSuite.TLS_RSA_PSK_WITH_AES_256_CBC_SHA384:
-                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_256_CBC, MacAlgorithm.hmac_sha384);
-
-            case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CCM:
-            case CipherSuite.TLS_PSK_WITH_AES_256_CCM:
-                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_256_CCM, MacAlgorithm.cls_null);
-
-            case CipherSuite.TLS_PSK_DHE_WITH_AES_256_CCM_8:
-            case CipherSuite.TLS_PSK_WITH_AES_256_CCM_8:
-                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_256_CCM_8, MacAlgorithm.cls_null);
-
-            case CipherSuite.TLS_DHE_PSK_WITH_AES_256_GCM_SHA384:
-            case CipherSuite.TLS_PSK_WITH_AES_256_GCM_SHA384:
-            case CipherSuite.TLS_RSA_PSK_WITH_AES_256_GCM_SHA384:
-                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_256_GCM, MacAlgorithm.cls_null);
-
-            case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256:
-            case CipherSuite.TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256:
-            case CipherSuite.TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256:
-            case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256:
-                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.CAMELLIA_128_CBC, MacAlgorithm.hmac_sha256);
-
-            case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256:
-            case CipherSuite.TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256:
-            case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256:
-                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.CAMELLIA_128_GCM, MacAlgorithm.cls_null);
-
-            case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384:
-            case CipherSuite.TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384:
-            case CipherSuite.TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384:
-            case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384:
-                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.CAMELLIA_256_CBC, MacAlgorithm.hmac_sha384);
-
-            case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384:
-            case CipherSuite.TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384:
-            case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384:
-                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.CAMELLIA_256_GCM, MacAlgorithm.cls_null);
-
-            case CipherSuite.TLS_DHE_PSK_WITH_ESTREAM_SALSA20_SHA1:
-            case CipherSuite.TLS_ECDHE_PSK_WITH_ESTREAM_SALSA20_SHA1:
-            case CipherSuite.TLS_PSK_WITH_ESTREAM_SALSA20_SHA1:
-            case CipherSuite.TLS_RSA_PSK_WITH_ESTREAM_SALSA20_SHA1:
-                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.ESTREAM_SALSA20, MacAlgorithm.hmac_sha1);
-
-            case CipherSuite.TLS_DHE_PSK_WITH_NULL_SHA:
-            case CipherSuite.TLS_ECDHE_PSK_WITH_NULL_SHA:
-            case CipherSuite.TLS_PSK_WITH_NULL_SHA:
-            case CipherSuite.TLS_RSA_PSK_WITH_NULL_SHA:
-                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.NULL, MacAlgorithm.hmac_sha1);
-                    
-            case CipherSuite.TLS_DHE_PSK_WITH_NULL_SHA256:
-            case CipherSuite.TLS_ECDHE_PSK_WITH_NULL_SHA256:
-            case CipherSuite.TLS_PSK_WITH_NULL_SHA256:
-            case CipherSuite.TLS_RSA_PSK_WITH_NULL_SHA256:
-                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.NULL, MacAlgorithm.hmac_sha256);
-
-            case CipherSuite.TLS_DHE_PSK_WITH_NULL_SHA384:
-            case CipherSuite.TLS_ECDHE_PSK_WITH_NULL_SHA384:
-            case CipherSuite.TLS_PSK_WITH_NULL_SHA384:
-            case CipherSuite.TLS_RSA_PSK_WITH_NULL_SHA384:
-                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.NULL, MacAlgorithm.hmac_sha384);
-
-            case CipherSuite.TLS_DHE_PSK_WITH_RC4_128_SHA:
-            case CipherSuite.TLS_ECDHE_PSK_WITH_RC4_128_SHA:
-            case CipherSuite.TLS_PSK_WITH_RC4_128_SHA:
-            case CipherSuite.TLS_RSA_PSK_WITH_RC4_128_SHA:
-                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.RC4_128, MacAlgorithm.hmac_sha1);
-
-            case CipherSuite.TLS_DHE_PSK_WITH_SALSA20_SHA1:
-            case CipherSuite.TLS_ECDHE_PSK_WITH_SALSA20_SHA1:
-            case CipherSuite.TLS_PSK_WITH_SALSA20_SHA1:
-            case CipherSuite.TLS_RSA_PSK_WITH_SALSA20_SHA1:
-                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.SALSA20, MacAlgorithm.hmac_sha1);
-
-            default:
-                /*
-                 * Note: internal error here; the TlsProtocol implementation verifies that the
-                 * server-selected cipher suite was in the list of client-offered cipher suites, so if
-                 * we now can't produce an implementation, we shouldn't have offered it!
-                 */
-                throw new TlsFatalAlert(AlertDescription.internal_error);
+                case KeyExchangeAlgorithm.DHE_PSK:
+                case KeyExchangeAlgorithm.ECDHE_PSK:
+                case KeyExchangeAlgorithm.PSK:
+                case KeyExchangeAlgorithm.RSA_PSK:
+                    return CreatePskKeyExchange(keyExchangeAlgorithm);
+
+                default:
+                    /*
+                     * Note: internal error here; the TlsProtocol implementation verifies that the
+                     * server-selected cipher suite was in the list of client-offered cipher suites, so if
+                     * we now can't produce an implementation, we shouldn't have offered it!
+                     */
+                    throw new TlsFatalAlert(AlertDescription.internal_error);
             }
         }
 
diff --git a/crypto/src/crypto/tls/SrpTlsClient.cs b/crypto/src/crypto/tls/SrpTlsClient.cs
index bed6a8f0c..df1607751 100644
--- a/crypto/src/crypto/tls/SrpTlsClient.cs
+++ b/crypto/src/crypto/tls/SrpTlsClient.cs
@@ -68,22 +68,14 @@ namespace Org.BouncyCastle.Crypto.Tls
 
         public override TlsKeyExchange GetKeyExchange()
         {
-            switch (mSelectedCipherSuite)
-            {
-            case CipherSuite.TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA:
-            case CipherSuite.TLS_SRP_SHA_WITH_AES_128_CBC_SHA:
-            case CipherSuite.TLS_SRP_SHA_WITH_AES_256_CBC_SHA:
-                return CreateSrpKeyExchange(KeyExchangeAlgorithm.SRP);
-
-            case CipherSuite.TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA:
-            case CipherSuite.TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA:
-            case CipherSuite.TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA:
-                return CreateSrpKeyExchange(KeyExchangeAlgorithm.SRP_RSA);
+            int keyExchangeAlgorithm = TlsUtilities.GetKeyExchangeAlgorithm(mSelectedCipherSuite);
 
-            case CipherSuite.TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA:
-            case CipherSuite.TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA:
-            case CipherSuite.TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA:
-                return CreateSrpKeyExchange(KeyExchangeAlgorithm.SRP_DSS);
+            switch (keyExchangeAlgorithm)
+            {
+            case KeyExchangeAlgorithm.SRP:
+            case KeyExchangeAlgorithm.SRP_DSS:
+            case KeyExchangeAlgorithm.SRP_RSA:
+                return CreateSrpKeyExchange(keyExchangeAlgorithm);
 
             default:
                 /*
@@ -104,35 +96,6 @@ namespace Org.BouncyCastle.Crypto.Tls
             throw new TlsFatalAlert(AlertDescription.internal_error);
         }
 
-        public override TlsCipher GetCipher()
-        {
-            switch (mSelectedCipherSuite)
-            {
-            case CipherSuite.TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA:
-            case CipherSuite.TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA:
-            case CipherSuite.TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA:
-                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.cls_3DES_EDE_CBC, MacAlgorithm.hmac_sha1);
-
-            case CipherSuite.TLS_SRP_SHA_WITH_AES_128_CBC_SHA:
-            case CipherSuite.TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA:
-            case CipherSuite.TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA:
-                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_128_CBC, MacAlgorithm.hmac_sha1);
-
-            case CipherSuite.TLS_SRP_SHA_WITH_AES_256_CBC_SHA:
-            case CipherSuite.TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA:
-            case CipherSuite.TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA:
-                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_256_CBC, MacAlgorithm.hmac_sha1);
-
-            default:
-                /*
-                 * Note: internal error here; the TlsProtocol implementation verifies that the
-                 * server-selected cipher suite was in the list of client-offered cipher suites, so if
-                 * we now can't produce an implementation, we shouldn't have offered it!
-                 */
-                throw new TlsFatalAlert(AlertDescription.internal_error);
-            }
-        }
-
         protected virtual TlsKeyExchange CreateSrpKeyExchange(int keyExchange)
         {
             return new TlsSrpKeyExchange(keyExchange, mSupportedSignatureAlgorithms, mGroupVerifier, mIdentity, mPassword);
diff --git a/crypto/src/crypto/tls/SrpTlsServer.cs b/crypto/src/crypto/tls/SrpTlsServer.cs
index 1bd6b3af4..f97878380 100644
--- a/crypto/src/crypto/tls/SrpTlsServer.cs
+++ b/crypto/src/crypto/tls/SrpTlsServer.cs
@@ -73,76 +73,35 @@ namespace Org.BouncyCastle.Crypto.Tls
 
         public override TlsCredentials GetCredentials()
         {
-            switch (mSelectedCipherSuite)
+            int keyExchangeAlgorithm = TlsUtilities.GetKeyExchangeAlgorithm(mSelectedCipherSuite);
+
+            switch (keyExchangeAlgorithm)
             {
-            case CipherSuite.TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA:
-            case CipherSuite.TLS_SRP_SHA_WITH_AES_128_CBC_SHA:
-            case CipherSuite.TLS_SRP_SHA_WITH_AES_256_CBC_SHA:
-                return null;
+                case KeyExchangeAlgorithm.SRP:
+                    return null;
 
-            case CipherSuite.TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA:
-            case CipherSuite.TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA:
-            case CipherSuite.TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA:
-                return GetDsaSignerCredentials();
+                case KeyExchangeAlgorithm.SRP_DSS:
+                    return GetDsaSignerCredentials();
 
-            case CipherSuite.TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA:
-            case CipherSuite.TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA:
-            case CipherSuite.TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA:
-                return GetRsaSignerCredentials();
+                case KeyExchangeAlgorithm.SRP_RSA:
+                    return GetRsaSignerCredentials();
 
-            default:
-                /* Note: internal error here; selected a key exchange we don't implement! */
-                throw new TlsFatalAlert(AlertDescription.internal_error);
+                default:
+                    /* Note: internal error here; selected a key exchange we don't implement! */
+                    throw new TlsFatalAlert(AlertDescription.internal_error);
             }
         }
 
         public override TlsKeyExchange GetKeyExchange()
         {
-            switch (mSelectedCipherSuite)
-            {
-            case CipherSuite.TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA:
-            case CipherSuite.TLS_SRP_SHA_WITH_AES_128_CBC_SHA:
-            case CipherSuite.TLS_SRP_SHA_WITH_AES_256_CBC_SHA:
-                return CreateSrpKeyExchange(KeyExchangeAlgorithm.SRP);
-
-            case CipherSuite.TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA:
-            case CipherSuite.TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA:
-            case CipherSuite.TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA:
-                return CreateSrpKeyExchange(KeyExchangeAlgorithm.SRP_RSA);
+            int keyExchangeAlgorithm = TlsUtilities.GetKeyExchangeAlgorithm(mSelectedCipherSuite);
 
-            case CipherSuite.TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA:
-            case CipherSuite.TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA:
-            case CipherSuite.TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA:
-                return CreateSrpKeyExchange(KeyExchangeAlgorithm.SRP_DSS);
-
-            default:
-                /*
-                 * Note: internal error here; the TlsProtocol implementation verifies that the
-                 * server-selected cipher suite was in the list of client-offered cipher suites, so if
-                 * we now can't produce an implementation, we shouldn't have offered it!
-                 */
-                throw new TlsFatalAlert(AlertDescription.internal_error);
-            }
-        }
-
-        public override TlsCipher GetCipher()
-        {
-            switch (mSelectedCipherSuite)
+            switch (keyExchangeAlgorithm)
             {
-            case CipherSuite.TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA:
-            case CipherSuite.TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA:
-            case CipherSuite.TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA:
-                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.cls_3DES_EDE_CBC, MacAlgorithm.hmac_sha1);
-
-            case CipherSuite.TLS_SRP_SHA_WITH_AES_128_CBC_SHA:
-            case CipherSuite.TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA:
-            case CipherSuite.TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA:
-                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_128_CBC, MacAlgorithm.hmac_sha1);
-
-            case CipherSuite.TLS_SRP_SHA_WITH_AES_256_CBC_SHA:
-            case CipherSuite.TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA:
-            case CipherSuite.TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA:
-                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_256_CBC, MacAlgorithm.hmac_sha1);
+            case KeyExchangeAlgorithm.SRP:
+            case KeyExchangeAlgorithm.SRP_DSS:
+            case KeyExchangeAlgorithm.SRP_RSA:
+                return CreateSrpKeyExchange(keyExchangeAlgorithm);
 
             default:
                 /*
diff --git a/crypto/src/crypto/tls/TlsUtilities.cs b/crypto/src/crypto/tls/TlsUtilities.cs
index be91e6c4b..a8c8a2b28 100644
--- a/crypto/src/crypto/tls/TlsUtilities.cs
+++ b/crypto/src/crypto/tls/TlsUtilities.cs
@@ -1531,6 +1531,528 @@ namespace Org.BouncyCastle.Crypto.Tls
             }
         }
 
+        public static int GetKeyExchangeAlgorithm(int ciphersuite)
+        {
+            switch (ciphersuite)
+            {
+            case CipherSuite.TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA:
+            case CipherSuite.TLS_DH_DSS_WITH_AES_128_CBC_SHA:
+            case CipherSuite.TLS_DH_DSS_WITH_AES_128_CBC_SHA256:
+            case CipherSuite.TLS_DH_DSS_WITH_AES_128_GCM_SHA256:
+            case CipherSuite.TLS_DH_DSS_WITH_AES_256_CBC_SHA:
+            case CipherSuite.TLS_DH_DSS_WITH_AES_256_CBC_SHA256:
+            case CipherSuite.TLS_DH_DSS_WITH_AES_256_GCM_SHA384:
+            case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA:
+            case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256:
+            case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256:
+            case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA:
+            case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256:
+            case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384:
+            case CipherSuite.TLS_DH_DSS_WITH_SEED_CBC_SHA:
+                return KeyExchangeAlgorithm.DH_DSS;
+
+            case CipherSuite.TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA:
+            case CipherSuite.TLS_DH_RSA_WITH_AES_128_CBC_SHA:
+            case CipherSuite.TLS_DH_RSA_WITH_AES_128_CBC_SHA256:
+            case CipherSuite.TLS_DH_RSA_WITH_AES_128_GCM_SHA256:
+            case CipherSuite.TLS_DH_RSA_WITH_AES_256_CBC_SHA:
+            case CipherSuite.TLS_DH_RSA_WITH_AES_256_CBC_SHA256:
+            case CipherSuite.TLS_DH_RSA_WITH_AES_256_GCM_SHA384:
+            case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA:
+            case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256:
+            case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256:
+            case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA:
+            case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256:
+            case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384:
+            case CipherSuite.TLS_DH_RSA_WITH_SEED_CBC_SHA:
+                return KeyExchangeAlgorithm.DH_RSA;
+
+            case CipherSuite.TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA:
+            case CipherSuite.TLS_DHE_DSS_WITH_AES_128_CBC_SHA:
+            case CipherSuite.TLS_DHE_DSS_WITH_AES_128_CBC_SHA256:
+            case CipherSuite.TLS_DHE_DSS_WITH_AES_128_GCM_SHA256:
+            case CipherSuite.TLS_DHE_DSS_WITH_AES_256_CBC_SHA:
+            case CipherSuite.TLS_DHE_DSS_WITH_AES_256_CBC_SHA256:
+            case CipherSuite.TLS_DHE_DSS_WITH_AES_256_GCM_SHA384:
+            case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA:
+            case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256:
+            case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256:
+            case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA:
+            case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256:
+            case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384:
+            case CipherSuite.TLS_DHE_DSS_WITH_SEED_CBC_SHA:
+                return KeyExchangeAlgorithm.DHE_DSS;
+
+            case CipherSuite.TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA:
+            case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CBC_SHA:
+            case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CBC_SHA256:
+            case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CCM:
+            case CipherSuite.TLS_DHE_PSK_WITH_AES_128_GCM_SHA256:
+            case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CBC_SHA:
+            case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CBC_SHA384:
+            case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CCM:
+            case CipherSuite.TLS_DHE_PSK_WITH_AES_256_GCM_SHA384:
+            case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256:
+            case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256:
+            case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384:
+            case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384:
+            case CipherSuite.TLS_DHE_PSK_WITH_ESTREAM_SALSA20_SHA1:
+            case CipherSuite.TLS_DHE_PSK_WITH_NULL_SHA:
+            case CipherSuite.TLS_DHE_PSK_WITH_NULL_SHA256:
+            case CipherSuite.TLS_DHE_PSK_WITH_NULL_SHA384:
+            case CipherSuite.TLS_DHE_PSK_WITH_RC4_128_SHA:
+            case CipherSuite.TLS_DHE_PSK_WITH_SALSA20_SHA1:
+            case CipherSuite.TLS_PSK_DHE_WITH_AES_128_CCM_8:
+            case CipherSuite.TLS_PSK_DHE_WITH_AES_256_CCM_8:
+                return KeyExchangeAlgorithm.DHE_PSK;
+
+            case CipherSuite.TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA:
+            case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA:
+            case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA256:
+            case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CCM:
+            case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CCM_8:
+            case CipherSuite.TLS_DHE_RSA_WITH_AES_128_GCM_SHA256:
+            case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA:
+            case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA256:
+            case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CCM:
+            case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CCM_8:
+            case CipherSuite.TLS_DHE_RSA_WITH_AES_256_GCM_SHA384:
+            case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA:
+            case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256:
+            case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256:
+            case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA:
+            case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256:
+            case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384:
+            case CipherSuite.TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256:
+            case CipherSuite.TLS_DHE_RSA_WITH_ESTREAM_SALSA20_SHA1:
+            case CipherSuite.TLS_DHE_RSA_WITH_SALSA20_SHA1:
+            case CipherSuite.TLS_DHE_RSA_WITH_SEED_CBC_SHA:
+                return KeyExchangeAlgorithm.DHE_RSA;
+
+            case CipherSuite.TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA:
+            case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA:
+            case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256:
+            case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256:
+            case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA:
+            case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384:
+            case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384:
+            case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256:
+            case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256:
+            case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384:
+            case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384:
+            case CipherSuite.TLS_ECDH_ECDSA_WITH_NULL_SHA:
+            case CipherSuite.TLS_ECDH_ECDSA_WITH_RC4_128_SHA:
+                return KeyExchangeAlgorithm.ECDH_ECDSA;
+
+            case CipherSuite.TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA:
+            case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_CBC_SHA:
+            case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256:
+            case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256:
+            case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_CBC_SHA:
+            case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384:
+            case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384:
+            case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256:
+            case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256:
+            case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384:
+            case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384:
+            case CipherSuite.TLS_ECDH_RSA_WITH_NULL_SHA:
+            case CipherSuite.TLS_ECDH_RSA_WITH_RC4_128_SHA:
+                return KeyExchangeAlgorithm.ECDH_RSA;
+
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CCM:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CCM:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_ESTREAM_SALSA20_SHA1:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_NULL_SHA:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_SALSA20_SHA1:
+                return KeyExchangeAlgorithm.ECDHE_ECDSA;
+
+            case CipherSuite.TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA:
+            case CipherSuite.TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA:
+            case CipherSuite.TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256:
+            case CipherSuite.TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA:
+            case CipherSuite.TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384:
+            case CipherSuite.TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256:
+            case CipherSuite.TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384:
+            case CipherSuite.TLS_ECDHE_PSK_WITH_ESTREAM_SALSA20_SHA1:
+            case CipherSuite.TLS_ECDHE_PSK_WITH_NULL_SHA:
+            case CipherSuite.TLS_ECDHE_PSK_WITH_NULL_SHA256:
+            case CipherSuite.TLS_ECDHE_PSK_WITH_NULL_SHA384:
+            case CipherSuite.TLS_ECDHE_PSK_WITH_RC4_128_SHA:
+            case CipherSuite.TLS_ECDHE_PSK_WITH_SALSA20_SHA1:
+                return KeyExchangeAlgorithm.ECDHE_PSK;
+
+            case CipherSuite.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_ESTREAM_SALSA20_SHA1:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_NULL_SHA:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_RC4_128_SHA:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_SALSA20_SHA1:
+                return KeyExchangeAlgorithm.ECDHE_RSA;
+
+            case CipherSuite.TLS_PSK_WITH_3DES_EDE_CBC_SHA:
+            case CipherSuite.TLS_PSK_WITH_AES_128_CBC_SHA:
+            case CipherSuite.TLS_PSK_WITH_AES_128_CBC_SHA256:
+            case CipherSuite.TLS_PSK_WITH_AES_128_CCM:
+            case CipherSuite.TLS_PSK_WITH_AES_128_CCM_8:
+            case CipherSuite.TLS_PSK_WITH_AES_128_GCM_SHA256:
+            case CipherSuite.TLS_PSK_WITH_AES_256_CBC_SHA:
+            case CipherSuite.TLS_PSK_WITH_AES_256_CBC_SHA384:
+            case CipherSuite.TLS_PSK_WITH_AES_256_CCM:
+            case CipherSuite.TLS_PSK_WITH_AES_256_CCM_8:
+            case CipherSuite.TLS_PSK_WITH_AES_256_GCM_SHA384:
+            case CipherSuite.TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256:
+            case CipherSuite.TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256:
+            case CipherSuite.TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384:
+            case CipherSuite.TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384:
+            case CipherSuite.TLS_PSK_WITH_ESTREAM_SALSA20_SHA1:
+            case CipherSuite.TLS_PSK_WITH_NULL_SHA:
+            case CipherSuite.TLS_PSK_WITH_NULL_SHA256:
+            case CipherSuite.TLS_PSK_WITH_NULL_SHA384:
+            case CipherSuite.TLS_PSK_WITH_RC4_128_SHA:
+            case CipherSuite.TLS_PSK_WITH_SALSA20_SHA1:
+                return KeyExchangeAlgorithm.PSK;
+
+            case CipherSuite.TLS_RSA_WITH_3DES_EDE_CBC_SHA:
+            case CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA:
+            case CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA256:
+            case CipherSuite.TLS_RSA_WITH_AES_128_CCM:
+            case CipherSuite.TLS_RSA_WITH_AES_128_CCM_8:
+            case CipherSuite.TLS_RSA_WITH_AES_128_GCM_SHA256:
+            case CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA:
+            case CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA256:
+            case CipherSuite.TLS_RSA_WITH_AES_256_CCM:
+            case CipherSuite.TLS_RSA_WITH_AES_256_CCM_8:
+            case CipherSuite.TLS_RSA_WITH_AES_256_GCM_SHA384:
+            case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_CBC_SHA:
+            case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256:
+            case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256:
+            case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_CBC_SHA:
+            case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256:
+            case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384:
+            case CipherSuite.TLS_RSA_WITH_ESTREAM_SALSA20_SHA1:
+            case CipherSuite.TLS_RSA_WITH_NULL_MD5:
+            case CipherSuite.TLS_RSA_WITH_NULL_SHA:
+            case CipherSuite.TLS_RSA_WITH_NULL_SHA256:
+            case CipherSuite.TLS_RSA_WITH_RC4_128_MD5:
+            case CipherSuite.TLS_RSA_WITH_RC4_128_SHA:
+            case CipherSuite.TLS_RSA_WITH_SALSA20_SHA1:
+            case CipherSuite.TLS_RSA_WITH_SEED_CBC_SHA:
+                return KeyExchangeAlgorithm.RSA;
+
+            case CipherSuite.TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA:
+            case CipherSuite.TLS_RSA_PSK_WITH_AES_128_CBC_SHA:
+            case CipherSuite.TLS_RSA_PSK_WITH_AES_128_CBC_SHA256:
+            case CipherSuite.TLS_RSA_PSK_WITH_AES_128_GCM_SHA256:
+            case CipherSuite.TLS_RSA_PSK_WITH_AES_256_CBC_SHA:
+            case CipherSuite.TLS_RSA_PSK_WITH_AES_256_CBC_SHA384:
+            case CipherSuite.TLS_RSA_PSK_WITH_AES_256_GCM_SHA384:
+            case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256:
+            case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256:
+            case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384:
+            case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384:
+            case CipherSuite.TLS_RSA_PSK_WITH_ESTREAM_SALSA20_SHA1:
+            case CipherSuite.TLS_RSA_PSK_WITH_NULL_SHA:
+            case CipherSuite.TLS_RSA_PSK_WITH_NULL_SHA256:
+            case CipherSuite.TLS_RSA_PSK_WITH_NULL_SHA384:
+            case CipherSuite.TLS_RSA_PSK_WITH_RC4_128_SHA:
+            case CipherSuite.TLS_RSA_PSK_WITH_SALSA20_SHA1:
+                return KeyExchangeAlgorithm.RSA_PSK;
+
+            case CipherSuite.TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA:
+            case CipherSuite.TLS_SRP_SHA_WITH_AES_128_CBC_SHA:
+            case CipherSuite.TLS_SRP_SHA_WITH_AES_256_CBC_SHA:
+                return KeyExchangeAlgorithm.SRP;
+
+            case CipherSuite.TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA:
+            case CipherSuite.TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA:
+            case CipherSuite.TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA:
+                return KeyExchangeAlgorithm.SRP_DSS;
+
+            case CipherSuite.TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA:
+            case CipherSuite.TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA:
+            case CipherSuite.TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA:
+                return KeyExchangeAlgorithm.SRP_RSA;
+
+            default:
+                throw new TlsFatalAlert(AlertDescription.internal_error);
+            }
+        }
+
+        public static int GetMacAlgorithm(int ciphersuite)
+        {
+            switch (ciphersuite)
+            {
+            case CipherSuite.TLS_DH_DSS_WITH_AES_128_GCM_SHA256:
+            case CipherSuite.TLS_DH_DSS_WITH_AES_256_GCM_SHA384:
+            case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256:
+            case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384:
+            case CipherSuite.TLS_DH_RSA_WITH_AES_128_GCM_SHA256:
+            case CipherSuite.TLS_DH_RSA_WITH_AES_256_GCM_SHA384:
+            case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256:
+            case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384:
+            case CipherSuite.TLS_DHE_DSS_WITH_AES_128_GCM_SHA256:
+            case CipherSuite.TLS_DHE_DSS_WITH_AES_256_GCM_SHA384:
+            case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256:
+            case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384:
+            case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CCM:
+            case CipherSuite.TLS_DHE_PSK_WITH_AES_128_GCM_SHA256:
+            case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CCM:
+            case CipherSuite.TLS_DHE_PSK_WITH_AES_256_GCM_SHA384:
+            case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256:
+            case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384:
+            case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CCM:
+            case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CCM_8:
+            case CipherSuite.TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256:
+            case CipherSuite.TLS_DHE_RSA_WITH_AES_128_GCM_SHA256:
+            case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CCM:
+            case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CCM_8:
+            case CipherSuite.TLS_DHE_RSA_WITH_AES_256_GCM_SHA384:
+            case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256:
+            case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384:
+            case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256:
+            case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384:
+            case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256:
+            case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384:
+            case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256:
+            case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384:
+            case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256:
+            case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CCM:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CCM:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256:
+            case CipherSuite.TLS_PSK_DHE_WITH_AES_128_CCM_8:
+            case CipherSuite.TLS_PSK_DHE_WITH_AES_256_CCM_8:
+            case CipherSuite.TLS_PSK_WITH_AES_128_CCM:
+            case CipherSuite.TLS_PSK_WITH_AES_128_CCM_8:
+            case CipherSuite.TLS_PSK_WITH_AES_128_GCM_SHA256:
+            case CipherSuite.TLS_PSK_WITH_AES_256_CCM:
+            case CipherSuite.TLS_PSK_WITH_AES_256_CCM_8:
+            case CipherSuite.TLS_PSK_WITH_AES_256_GCM_SHA384:
+            case CipherSuite.TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256:
+            case CipherSuite.TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384:
+            case CipherSuite.TLS_RSA_PSK_WITH_AES_128_GCM_SHA256:
+            case CipherSuite.TLS_RSA_PSK_WITH_AES_256_GCM_SHA384:
+            case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256:
+            case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384:
+            case CipherSuite.TLS_RSA_WITH_AES_128_CCM:
+            case CipherSuite.TLS_RSA_WITH_AES_128_CCM_8:
+            case CipherSuite.TLS_RSA_WITH_AES_128_GCM_SHA256:
+            case CipherSuite.TLS_RSA_WITH_AES_256_CCM:
+            case CipherSuite.TLS_RSA_WITH_AES_256_CCM_8:
+            case CipherSuite.TLS_RSA_WITH_AES_256_GCM_SHA384:
+            case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256:
+            case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384:
+                return MacAlgorithm.cls_null;
+
+            case CipherSuite.TLS_RSA_WITH_NULL_MD5:
+            case CipherSuite.TLS_RSA_WITH_RC4_128_MD5:
+                return MacAlgorithm.hmac_md5;
+
+            case CipherSuite.TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA:
+            case CipherSuite.TLS_DH_DSS_WITH_AES_128_CBC_SHA:
+            case CipherSuite.TLS_DH_DSS_WITH_AES_256_CBC_SHA:
+            case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA:
+            case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA:
+            case CipherSuite.TLS_DH_DSS_WITH_SEED_CBC_SHA:
+            case CipherSuite.TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA:
+            case CipherSuite.TLS_DH_RSA_WITH_AES_128_CBC_SHA:
+            case CipherSuite.TLS_DH_RSA_WITH_AES_256_CBC_SHA:
+            case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA:
+            case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA:
+            case CipherSuite.TLS_DH_RSA_WITH_SEED_CBC_SHA:
+            case CipherSuite.TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA:
+            case CipherSuite.TLS_DHE_DSS_WITH_AES_128_CBC_SHA:
+            case CipherSuite.TLS_DHE_DSS_WITH_AES_256_CBC_SHA:
+            case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA:
+            case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA:
+            case CipherSuite.TLS_DHE_DSS_WITH_SEED_CBC_SHA:
+            case CipherSuite.TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA:
+            case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CBC_SHA:
+            case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CBC_SHA:
+            case CipherSuite.TLS_DHE_PSK_WITH_ESTREAM_SALSA20_SHA1:
+            case CipherSuite.TLS_DHE_PSK_WITH_NULL_SHA:
+            case CipherSuite.TLS_DHE_PSK_WITH_RC4_128_SHA:
+            case CipherSuite.TLS_DHE_PSK_WITH_SALSA20_SHA1:
+            case CipherSuite.TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA:
+            case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA:
+            case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA:
+            case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA:
+            case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA:
+            case CipherSuite.TLS_DHE_RSA_WITH_ESTREAM_SALSA20_SHA1:
+            case CipherSuite.TLS_DHE_RSA_WITH_SALSA20_SHA1:
+            case CipherSuite.TLS_DHE_RSA_WITH_SEED_CBC_SHA:
+            case CipherSuite.TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA:
+            case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA:
+            case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA:
+            case CipherSuite.TLS_ECDH_ECDSA_WITH_NULL_SHA:
+            case CipherSuite.TLS_ECDH_ECDSA_WITH_RC4_128_SHA:
+            case CipherSuite.TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA:
+            case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_CBC_SHA:
+            case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_CBC_SHA:
+            case CipherSuite.TLS_ECDH_RSA_WITH_NULL_SHA:
+            case CipherSuite.TLS_ECDH_RSA_WITH_RC4_128_SHA:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_ESTREAM_SALSA20_SHA1:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_NULL_SHA:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_SALSA20_SHA1:
+            case CipherSuite.TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA:
+            case CipherSuite.TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA:
+            case CipherSuite.TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA:
+            case CipherSuite.TLS_ECDHE_PSK_WITH_ESTREAM_SALSA20_SHA1:
+            case CipherSuite.TLS_ECDHE_PSK_WITH_NULL_SHA:
+            case CipherSuite.TLS_ECDHE_PSK_WITH_RC4_128_SHA:
+            case CipherSuite.TLS_ECDHE_PSK_WITH_SALSA20_SHA1:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_ESTREAM_SALSA20_SHA1:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_NULL_SHA:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_RC4_128_SHA:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_SALSA20_SHA1:
+            case CipherSuite.TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA:
+            case CipherSuite.TLS_RSA_PSK_WITH_AES_128_CBC_SHA:
+            case CipherSuite.TLS_RSA_PSK_WITH_AES_256_CBC_SHA:
+            case CipherSuite.TLS_PSK_WITH_3DES_EDE_CBC_SHA:
+            case CipherSuite.TLS_PSK_WITH_AES_128_CBC_SHA:
+            case CipherSuite.TLS_PSK_WITH_AES_256_CBC_SHA:
+            case CipherSuite.TLS_PSK_WITH_ESTREAM_SALSA20_SHA1:
+            case CipherSuite.TLS_PSK_WITH_NULL_SHA:
+            case CipherSuite.TLS_PSK_WITH_RC4_128_SHA:
+            case CipherSuite.TLS_PSK_WITH_SALSA20_SHA1:
+            case CipherSuite.TLS_RSA_PSK_WITH_ESTREAM_SALSA20_SHA1:
+            case CipherSuite.TLS_RSA_PSK_WITH_NULL_SHA:
+            case CipherSuite.TLS_RSA_PSK_WITH_RC4_128_SHA:
+            case CipherSuite.TLS_RSA_PSK_WITH_SALSA20_SHA1:
+            case CipherSuite.TLS_RSA_WITH_3DES_EDE_CBC_SHA:
+            case CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA:
+            case CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA:
+            case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_CBC_SHA:
+            case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_CBC_SHA:
+            case CipherSuite.TLS_RSA_WITH_ESTREAM_SALSA20_SHA1:
+            case CipherSuite.TLS_RSA_WITH_NULL_SHA:
+            case CipherSuite.TLS_RSA_WITH_RC4_128_SHA:
+            case CipherSuite.TLS_RSA_WITH_SALSA20_SHA1:
+            case CipherSuite.TLS_RSA_WITH_SEED_CBC_SHA:
+            case CipherSuite.TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA:
+            case CipherSuite.TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA:
+            case CipherSuite.TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA:
+            case CipherSuite.TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA:
+            case CipherSuite.TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA:
+            case CipherSuite.TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA:
+            case CipherSuite.TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA:
+            case CipherSuite.TLS_SRP_SHA_WITH_AES_128_CBC_SHA:
+            case CipherSuite.TLS_SRP_SHA_WITH_AES_256_CBC_SHA:
+                return MacAlgorithm.hmac_sha1;
+
+            case CipherSuite.TLS_DH_DSS_WITH_AES_128_CBC_SHA256:
+            case CipherSuite.TLS_DH_DSS_WITH_AES_256_CBC_SHA256:
+            case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256:
+            case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256:
+            case CipherSuite.TLS_DH_RSA_WITH_AES_128_CBC_SHA256:
+            case CipherSuite.TLS_DH_RSA_WITH_AES_256_CBC_SHA256:
+            case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256:
+            case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256:
+            case CipherSuite.TLS_DHE_DSS_WITH_AES_128_CBC_SHA256:
+            case CipherSuite.TLS_DHE_DSS_WITH_AES_256_CBC_SHA256:
+            case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256:
+            case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256:
+            case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CBC_SHA256:
+            case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256:
+            case CipherSuite.TLS_DHE_PSK_WITH_NULL_SHA256:
+            case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA256:
+            case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA256:
+            case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256:
+            case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256:
+            case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256:
+            case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256:
+            case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256:
+            case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256:
+            case CipherSuite.TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256:
+            case CipherSuite.TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256:
+            case CipherSuite.TLS_ECDHE_PSK_WITH_NULL_SHA256:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256:
+            case CipherSuite.TLS_PSK_WITH_AES_128_CBC_SHA256:
+            case CipherSuite.TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256:
+            case CipherSuite.TLS_PSK_WITH_NULL_SHA256:
+            case CipherSuite.TLS_RSA_PSK_WITH_AES_128_CBC_SHA256:
+            case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256:
+            case CipherSuite.TLS_RSA_PSK_WITH_NULL_SHA256:
+            case CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA256:
+            case CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA256:
+            case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256:
+            case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256:
+            case CipherSuite.TLS_RSA_WITH_NULL_SHA256:
+                return MacAlgorithm.hmac_sha256;
+
+            case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CBC_SHA384:
+            case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384:
+            case CipherSuite.TLS_DHE_PSK_WITH_NULL_SHA384:
+            case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384:
+            case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384:
+            case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384:
+            case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384:
+            case CipherSuite.TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384:
+            case CipherSuite.TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384:
+            case CipherSuite.TLS_ECDHE_PSK_WITH_NULL_SHA384:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384:
+            case CipherSuite.TLS_PSK_WITH_AES_256_CBC_SHA384:
+            case CipherSuite.TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384:
+            case CipherSuite.TLS_PSK_WITH_NULL_SHA384:
+            case CipherSuite.TLS_RSA_PSK_WITH_AES_256_CBC_SHA384:
+            case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384:
+            case CipherSuite.TLS_RSA_PSK_WITH_NULL_SHA384:
+                return MacAlgorithm.hmac_sha384;
+
+            default:
+                throw new TlsFatalAlert(AlertDescription.internal_error);
+            }
+        }
+
         public static ProtocolVersion GetMinimumVersion(int ciphersuite)
         {
             switch (ciphersuite)