summary refs log tree commit diff
path: root/crypto
diff options
context:
space:
mode:
authorPeter Dettman <peter.dettman@bouncycastle.org>2017-03-30 01:54:32 +1030
committerPeter Dettman <peter.dettman@bouncycastle.org>2017-03-30 01:54:32 +1030
commit4f46fe2c101b74cc594bae681c1591ee8c968bf0 (patch)
treeaeb28fa49d3321c6b966ecce93e9e9802c36dd2c /crypto
parentFix fatal alert type for unexpected server_hello_done (diff)
downloadBouncyCastle.NET-ed25519-4f46fe2c101b74cc594bae681c1591ee8c968bf0.tar.xz
Check candidate cipher suites against signature_algorithms
Diffstat (limited to 'crypto')
-rw-r--r--crypto/src/crypto/tls/AbstractTlsServer.cs6
-rw-r--r--crypto/src/crypto/tls/TlsUtilities.cs69
2 files changed, 73 insertions, 2 deletions
diff --git a/crypto/src/crypto/tls/AbstractTlsServer.cs b/crypto/src/crypto/tls/AbstractTlsServer.cs
index d87a294f0..52a79c9d8 100644
--- a/crypto/src/crypto/tls/AbstractTlsServer.cs
+++ b/crypto/src/crypto/tls/AbstractTlsServer.cs
@@ -194,11 +194,12 @@ namespace Org.BouncyCastle.Crypto.Tls
         public virtual int GetSelectedCipherSuite()
         {
             /*
-             * TODO RFC 5246 7.4.3. In order to negotiate correctly, the server MUST check any candidate
+             * RFC 5246 7.4.3. In order to negotiate correctly, the server MUST check any candidate
              * cipher suites against the "signature_algorithms" extension before selecting them. This is
              * somewhat inelegant but is a compromise designed to minimize changes to the original
              * cipher suite design.
              */
+            IList sigAlgs = TlsUtilities.GetUsableSignatureAlgorithms(this.mSupportedSignatureAlgorithms);
 
             /*
              * RFC 4429 5.1. A server that receives a ClientHello containing one or both of these
@@ -216,7 +217,8 @@ namespace Org.BouncyCastle.Crypto.Tls
 
                 if (Arrays.Contains(this.mOfferedCipherSuites, cipherSuite)
                     && (eccCipherSuitesEnabled || !TlsEccUtilities.IsEccCipherSuite(cipherSuite))
-                    && TlsUtilities.IsValidCipherSuiteForVersion(cipherSuite, mServerVersion))
+                    && TlsUtilities.IsValidCipherSuiteForVersion(cipherSuite, mServerVersion)
+                    && TlsUtilities.IsValidCipherSuiteForSignatureAlgorithms(cipherSuite, sigAlgs))
                 {
                     return this.mSelectedCipherSuite = cipherSuite;
                 }
diff --git a/crypto/src/crypto/tls/TlsUtilities.cs b/crypto/src/crypto/tls/TlsUtilities.cs
index 4f709a645..48e51a7b6 100644
--- a/crypto/src/crypto/tls/TlsUtilities.cs
+++ b/crypto/src/crypto/tls/TlsUtilities.cs
@@ -571,6 +571,16 @@ namespace Org.BouncyCastle.Crypto.Tls
             buf[offset + 1] = (byte)version.MinorVersion;
         }
 
+        public static IList GetAllSignatureAlgorithms()
+        {
+            IList v = Platform.CreateArrayList(4);
+            v.Add(SignatureAlgorithm.anonymous);
+            v.Add(SignatureAlgorithm.rsa);
+            v.Add(SignatureAlgorithm.dsa);
+            v.Add(SignatureAlgorithm.ecdsa);
+            return v;
+        }
+
         public static IList GetDefaultDssSignatureAlgorithms()
         {
             return VectorOfOne(new SignatureAndHashAlgorithm(HashAlgorithm.sha1, SignatureAlgorithm.dsa));
@@ -2286,9 +2296,68 @@ namespace Org.BouncyCastle.Crypto.Tls
             return CipherType.stream == GetCipherType(ciphersuite);
         }
 
+        public static bool IsValidCipherSuiteForSignatureAlgorithms(int cipherSuite, IList sigAlgs)
+        {
+            int keyExchangeAlgorithm;
+            try
+            {
+                keyExchangeAlgorithm = GetKeyExchangeAlgorithm(cipherSuite);
+            }
+            catch (IOException e)
+            {
+                return true;
+            }
+
+            switch (keyExchangeAlgorithm)
+            {
+            case KeyExchangeAlgorithm.DH_anon:
+            case KeyExchangeAlgorithm.DH_anon_EXPORT:
+            case KeyExchangeAlgorithm.ECDH_anon:
+                return sigAlgs.Contains(SignatureAlgorithm.anonymous);
+
+            case KeyExchangeAlgorithm.DHE_RSA:
+            case KeyExchangeAlgorithm.DHE_RSA_EXPORT:
+            case KeyExchangeAlgorithm.ECDHE_RSA:
+            case KeyExchangeAlgorithm.SRP_RSA:
+                return sigAlgs.Contains(SignatureAlgorithm.rsa);
+
+            case KeyExchangeAlgorithm.DHE_DSS:
+            case KeyExchangeAlgorithm.DHE_DSS_EXPORT:
+            case KeyExchangeAlgorithm.SRP_DSS:
+                return sigAlgs.Contains(SignatureAlgorithm.dsa);
+
+            case KeyExchangeAlgorithm.ECDHE_ECDSA:
+                return sigAlgs.Contains(SignatureAlgorithm.ecdsa);
+
+            default:
+                return true;
+            }
+        }
+
         public static bool IsValidCipherSuiteForVersion(int cipherSuite, ProtocolVersion serverVersion)
         {
             return GetMinimumVersion(cipherSuite).IsEqualOrEarlierVersionOf(serverVersion.GetEquivalentTLSVersion());
         }
+
+        public static IList GetUsableSignatureAlgorithms(IList sigHashAlgs)
+        {
+            if (sigHashAlgs == null)
+                return GetAllSignatureAlgorithms();
+
+            IList v = Platform.CreateArrayList(4);
+            v.Add(SignatureAlgorithm.anonymous);
+            foreach (SignatureAndHashAlgorithm sigHashAlg in sigHashAlgs)
+            {
+                //if (sigHashAlg.Hash >= MINIMUM_HASH_STRICT)
+                {
+                    byte sigAlg = sigHashAlg.Signature;
+                    if (!v.Contains(sigAlg))
+                    {
+                        v.Add(sigAlg);
+                    }
+                }
+            }
+            return v;
+        }
     }
 }