diff options
author | Peter Dettman <peter.dettman@bouncycastle.org> | 2017-03-30 01:54:32 +1030 |
---|---|---|
committer | Peter Dettman <peter.dettman@bouncycastle.org> | 2017-03-30 01:54:32 +1030 |
commit | 4f46fe2c101b74cc594bae681c1591ee8c968bf0 (patch) | |
tree | aeb28fa49d3321c6b966ecce93e9e9802c36dd2c | |
parent | Fix fatal alert type for unexpected server_hello_done (diff) | |
download | BouncyCastle.NET-ed25519-4f46fe2c101b74cc594bae681c1591ee8c968bf0.tar.xz |
Check candidate cipher suites against signature_algorithms
-rw-r--r-- | crypto/src/crypto/tls/AbstractTlsServer.cs | 6 | ||||
-rw-r--r-- | crypto/src/crypto/tls/TlsUtilities.cs | 69 |
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; + } } } |