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;
+ }
}
}
|